Compare commits

...

181 Commits

Author SHA1 Message Date
David Given
ca66e3c35c Merge pull request #218 from hpingel/ibm_enc_swapsides_preset_1581
Adding preset for Commodore 1581 (cbm1581) to IBM writer frontend
2021-02-16 21:01:19 +01:00
hpingel
320f32895a adding preset cbm1581 to ibm writer frontend 2021-01-18 23:08:33 +01:00
David Given
d4db131d3c Merge pull request #217 from davidgiven/writes
Update sequencer to not lose one tick from every non-zero interval.
2021-01-18 11:22:02 +01:00
David Given
27c2c9045e Update sequencer to not lose one tick from every non-zero interval. 2021-01-18 00:27:00 +01:00
David Given
f97b7c7d62 Merge pull request #215 from davidgiven/ibm
Fix the timing when writing IBM 1440kB disks.
2021-01-17 19:39:30 +01:00
David Given
9eb33d31ac Merge from master. 2021-01-17 18:57:49 +01:00
David Given
6dd84d6fc2 Add swapSides parameter to the Atari ST writer. 2021-01-17 18:53:43 +01:00
David Given
daddd60581 Merge branch 'ibm_enc_swapsides' of https://github.com/hpingel/fluxengine into hpingel-ibm_enc_swapsides 2021-01-17 18:43:31 +01:00
David Given
e832723ee4 Merge pull request #203 from keithclark/atari-st-format
Write Atari ST formats
2021-01-17 18:34:40 +01:00
Keith Clark
35f4a63c0e Fix type in IBM disk documentation 2021-01-17 14:02:37 +00:00
Keith Clark
28478ea4ac Add Atari ST disk documentation 2021-01-17 14:02:37 +00:00
Keith Clark
0f93a68694 Add Atari ST disk reader front-end 2021-01-17 14:02:37 +00:00
Keith Clark
1a2d5d13b3 Add .st to list of supported extensions 2021-01-17 14:02:37 +00:00
Keith Clark
5f2894fc5b Add support for writing Atari ST floppy formats 2021-01-17 14:02:37 +00:00
hpingel
66cb39dce2 added parameter swapSides to IBM encoder 2021-01-17 12:54:14 +01:00
David Given
d44c871c54 Remove stray debug tracing. 2021-01-16 22:26:54 +01:00
David Given
dff0378ba8 Fix timings for 1440kB disks. 2021-01-16 22:26:45 +01:00
David Given
4f7b1b7140 Merge pull request #212 from davidgiven/analysis
Rework the disk response analyser to draw its own graphs
2021-01-15 10:52:44 +01:00
David Given
662514304b Merge from master. 2021-01-14 01:24:19 +01:00
David Given
0913e9e0c0 Allow saving the other image formats supported by libstb. 2021-01-13 20:34:21 +01:00
David Given
d403733627 Update graphs and documentation. 2021-01-13 20:05:13 +01:00
David Given
fae5b439d0 Fix buffer overrun bug. 2021-01-13 20:01:36 +01:00
David Given
bc66de6d85 Can't initialise variable-sized objects. 2021-01-13 10:43:16 +01:00
David Given
57e598156c Add support to analyse driveresponse for drawing its own graphs via AGG. 2021-01-13 01:46:48 +01:00
David Given
b570e44ee4 Merge pull request #211 from davidgiven/patch-1
Add missing zlib dependency.
2021-01-11 11:59:22 +01:00
David Given
b115d0b55b Add missing zlib dependency.
Fixes: #190
2021-01-11 11:57:59 +01:00
David Given
03fc1419de Archival checkin of partial work towards drawing my own graphs. 2021-01-11 00:56:09 +01:00
David Given
a833aa0a00 Import STB's image writer library and hook it up to AGG. 2021-01-10 16:38:49 +01:00
David Given
52332b04ac Import the AGG graphics library. 2021-01-10 14:45:32 +01:00
David Given
529488cab0 Typo fix. 2021-01-10 13:55:55 +01:00
David Given
b2429a7ca3 Typo fixes. 2021-01-10 12:34:55 +01:00
David Given
0bce12d3b4 Merge pull request #210 from davidgiven/analysis
Add the drive response documentation page.
2021-01-10 12:26:09 +01:00
David Given
75f557cb18 Add the drive response documentation page. 2021-01-10 12:15:37 +01:00
David Given
035dd1fad1 Merge pull request #209 from davidgiven/analyse
Add an analysis tool for checking drive response.
2021-01-10 02:01:33 +01:00
David Given
d2df79a665 Remember to get rid of the junk comments! 2021-01-10 01:09:35 +01:00
David Given
103e0a13bb Typo fix. 2021-01-10 01:06:13 +01:00
David Given
d1b5eec84a Add the analysis tool and Python script for drawing the results. 2021-01-10 00:51:43 +01:00
David Given
6b1e6b31ed Add initial version of the response analysis tool. 2021-01-09 13:42:37 +01:00
David Given
f6f6db913e Merge pull request #208 from davidgiven/greaseweazel
Add client support for the GreaseWeazle.
2021-01-09 01:12:10 +01:00
David Given
ec0a6416fd Update documentation. 2021-01-09 00:52:16 +01:00
David Given
1787402be9 ...and again. 2021-01-09 00:45:27 +01:00
David Given
5f6d99f138 Attempt that fix again. 2021-01-09 00:37:37 +01:00
David Given
d1e2b0d1f8 Fix an issue with old C++ compilers and designated initialisers. 2021-01-09 00:29:46 +01:00
David Given
c2c51bbe33 Fix after merge. 2021-01-09 00:02:14 +01:00
David Given
bb806e3853 Merge from master. 2021-01-08 23:23:50 +01:00
David Given
a11d0e75c8 Merge pull request #200 from ejona86/hard-sectors
Add firmware support for hard sectors
2021-01-08 23:20:40 +01:00
David Given
5406ff0ea3 Typo fix. 2021-01-08 23:14:51 +01:00
David Given
c88317b44a Document how to make things work on Windows. 2021-01-08 23:13:27 +01:00
David Given
6898062d66 Document Windows horror. 2021-01-08 21:37:44 +01:00
David Given
6e1f264e6a Make --sync-with-index and --revolutions work properly on the GreaseWeazle. 2021-01-08 21:36:50 +01:00
David Given
082be14232 Add GreaseWeazle support for --high-density. 2021-01-08 21:20:33 +01:00
David Given
231aa44d03 The clock compensation factor for Mac doesn't seem to be needed? 2021-01-08 01:14:39 +01:00
David Given
cdb12f35d4 Update documentation to mention the GreaseWeazle. 2021-01-07 23:03:34 +01:00
David Given
e831ee8b44 Add erase support. 2021-01-07 22:46:11 +01:00
David Given
40e9a6082f Remove that 'packed' thing. 2021-01-07 22:17:19 +01:00
David Given
53cec292d0 Refactor the GreaseWeazle converter to allow it to be tested. 2021-01-07 22:06:45 +01:00
David Given
3f85309ee5 Commit non-functioning GreaseWeazle write support. 2021-01-07 20:42:06 +01:00
David Given
70944f8521 Reading flux now correctly handles index markers. 2021-01-07 20:02:51 +01:00
David Given
2ab00c42ff Handle index pulses on read. 2021-01-07 01:05:23 +01:00
David Given
a572742caa I read my first disk using the GreaseWeazel! 2021-01-07 00:58:19 +01:00
David Given
400e5f8580 The bandwidth tester works. 2021-01-06 23:24:28 +01:00
David Given
74f0fd89b6 We can successfully seek on the GreaseWeazle. 2021-01-06 22:52:52 +01:00
David Given
09f9bea7a2 Add boilerplate for the GreaseWeazle driver. 2021-01-06 20:39:13 +01:00
David Given
8bffb38117 Fix bad merge. 2021-01-05 02:16:55 +01:00
David Given
eb5d545c35 Remember to unicornify the Mac formats. 2021-01-05 02:09:47 +01:00
David Given
a79a545730 Merge pull request #205 from davidgiven/writemac
Add Macintosh write support.
2021-01-05 02:08:52 +01:00
David Given
3863dab944 Try to fix an AppVeyor issue. 2021-01-05 01:56:49 +01:00
David Given
e53b7ecd8b Rebuild firmware. 2021-01-05 01:51:29 +01:00
David Given
7d88673ed5 Merge from trunk. 2021-01-05 01:36:54 +01:00
David Given
41f2da71e4 Merge. 2021-01-05 01:36:10 +01:00
David Given
cb4ee0fd74 Comment typo fix. 2021-01-05 01:36:00 +01:00
David Given
088381a5a6 Add a DiskCopy 4.2 image reader. We can now write files to floppy, and they
almost work.
2021-01-05 00:36:06 +01:00
David Given
629af2a697 You can now create Bytes from strings and vice versa. 2021-01-04 23:31:54 +01:00
David Given
884edfd497 Tweak the Mac encoder parameters to work. 2021-01-04 23:06:15 +01:00
David Given
83dd9e462e Fix sequencer bug where intervals of 0 would go horribly wrong. 2021-01-04 22:06:19 +01:00
David Given
70a6dfd98a Warning fix. 2021-01-04 20:16:36 +01:00
David Given
7f5d96382b Update PSoC components. 2021-01-04 20:16:15 +01:00
David Given
fd4d1c4bb7 Writing Mac disks now looks like it's about half working, but some of the
tracks are ending up mangled on disk --- maybe it's a firmware bug?
2021-01-04 19:16:09 +01:00
David Given
7eaf3de572 Mac encoder is code-complete. 2021-01-04 17:48:59 +01:00
David Given
4b608de3fb Merge pull request #186 from davidgiven/8inch
Add some utility features for 8" drives
2021-01-04 01:50:59 +01:00
David Given
b47e6e852b Merge pull request #188 from davidgiven/jv3
Add support for reading TRS-80 JV3 images.
2021-01-04 01:50:38 +01:00
David Given
a8a8ce4a36 Do the basic skeleton of the writer. 2021-01-04 01:49:15 +01:00
David Given
c61376d5a1 Add skeleton of Mac encoder. 2021-01-04 00:50:12 +01:00
Eric Anderson
d3a5bb08d3 Set drive before checking rotation speed for writing 2020-12-24 23:11:34 -08:00
Eric Anderson
f1506d0dbd Add firmware support for hard sectors 2020-12-24 17:39:52 -08:00
David Given
15e6d4959e Adjust Micropolis documentation. 2020-10-11 18:49:00 +02:00
David Given
41216fd1cd Merge pull request #191 from ejona86/micropolis
Add Micropolis decoder
2020-10-11 18:52:31 +02:00
Eric Anderson
b8786866db Fix carry handling in Micropolis checksum
Two bugs make a right, mostly. The very last carry should be ignored and
when adding the low and high bytes they commonly would commonly produce
a carry which was being ignored. On the test disks these two bugs
cancelled themselves out, except only for track 1, side 1, sector 0. I
had noticed it was suspicously off-by-one earlier for both test disks,
but the cause wasn't obvious.

On some old 1980s disks, with real data, it changed number of bad
sectors from 224 (out of 2464) to 5 for one disk and 81 to 3 for
another.
2020-10-04 19:55:25 -05:00
Eric Anderson
82bd1bead4 Add Micropolis decoder
Resolves #187
2020-10-03 13:05:06 -05:00
David Given
6e2bdcad79 Document the JV3 format. 2020-09-18 00:56:02 +02:00
David Given
ef3c9f3d03 Add the fe-image command and the TRS-80 JV3 file reader. 2020-09-18 00:53:39 +02:00
David Given
5427f24df2 Merge from master. 2020-09-13 19:35:47 +02:00
David Given
b374340303 Try multiplexing SIDE1 onto DIR. 2020-09-10 22:07:47 +02:00
David Given
c78ed2c6ad Add the TK43 pin, which goes low when seeking to track 43 or above. 2020-09-10 21:48:30 +02:00
David Given
3b02bc8cf1 Merge pull request #183 from davidgiven/ds990
Add support for TI DS990 disks.
2020-09-10 21:19:10 +02:00
David Given
c7e48a7e76 Unicorn the DS990 format. 2020-09-10 20:10:54 +02:00
David Given
77d125c03d Typo fix. 2020-08-22 12:38:10 +02:00
David Given
8aa52aeefd Add documentation for the DS990. 2020-08-22 12:37:11 +02:00
David Given
0bab038454 Make the DS990 encoder work, maybe? 2020-08-22 00:36:48 +02:00
David Given
6c3b49f4d0 Add the DS990 encoder skeleton. 2020-08-21 23:07:35 +02:00
David Given
03dd689f17 Make the DS990 decoder work. 2020-08-21 00:32:36 +02:00
David Given
c375c948c0 Add boilerplate for the TI DS990 decoder. 2020-08-20 22:41:14 +02:00
David Given
cbcf457ce3 Merge pull request #182 from davidgiven/usb
Add support for multiple simultaneously connected FluxEngines.
2020-08-10 23:32:16 +02:00
David Given
4855f825e2 Show serial number on device connection, and improve the device listing a bit. 2020-08-10 23:16:04 +02:00
David Given
85bc1637f2 Document the use of multiple FluxEngines. 2020-08-10 23:12:33 +02:00
David Given
73398b83a9 Add support for specifying which FluxEngine you want to use with the --devices
parameter.
2020-08-10 22:36:47 +02:00
David Given
2727e66d40 Allow multiple USB implementations. 2020-08-09 22:33:54 +02:00
David Given
8b6be5a501 Move usb.{cc,h} into its own directory. 2020-08-09 21:14:09 +02:00
David Given
4fee29307c Refactor the USB stuff to allow for multiple USB implementations. 2020-08-08 14:52:11 +01:00
David Given
35f8249c67 Merge pull request #178 from davidgiven/mac
Add support for exporting to DiskCopy 4.2 Mac disk image
2020-08-02 17:42:48 +01:00
David Given
d1467a14b8 Merge. 2020-08-02 18:24:15 +02:00
David Given
3e6b9eb74d Document the .diskcopy file format. 2020-08-02 18:22:30 +02:00
David Given
ce2e8fb4b5 First draft of the DiskCopy 4.2 image writer. 2020-07-30 20:21:49 +01:00
David Given
7eaa75c05d Merge pull request #177 from davidgiven/mac
Make Mac double-sided disks work.
2020-07-29 00:38:28 +02:00
David Given
e86de4483a Fix stupid bug where the mac decoder was looking at the wrong bit for the side
data.
2020-07-28 01:25:50 +02:00
David Given
203a74713f Merge pull request #175 from davidgiven/scp
Make SCP import and export properly handle single-sided images.
2020-06-30 11:19:48 +02:00
David Given
59ed2a6793 Make SCP import and export properly handle single-sided images. 2020-06-26 20:25:56 +02:00
David Given
a03283ce64 Merge pull request #174 from davidgiven/scp
Fix the SCP exporter.
2020-06-26 15:40:41 +02:00
David Given
984cdaeb03 Make nanoseconds_t a double to prevent overflow on very large numbers of
revolutions (I've just seen a flux file with 50).
2020-06-26 14:47:25 +02:00
David Given
a1ed4a9171 Fill out the SCP checksum correctly, and add a --indexed mode which causes data
prior to the first index mark to be discarded and sets the INDEX bit in the
header.
2020-06-26 12:20:49 +02:00
David Given
93caf8e549 Merge pull request #172 from davidgiven/b169
Fix a crash when decoding MX disks if advanceToNextRecord finds no records in a track.
2020-06-25 22:15:00 +02:00
David Given
3841942153 Fix a crash when decoding MX disks if advanceToNextRecord finds no records in a
track.
2020-06-25 21:56:33 +02:00
David Given
5706877b67 Merge pull request #171 from davidgiven/newsampler
Manually merge in jboone's new sampler from #164
2020-06-25 21:16:11 +02:00
David Given
d60900262b Remove the pulse converters from the sampler (the new sampler doesn't require
them). Update firmware.
2020-06-25 21:07:58 +02:00
David Given
54ea34400b Merge in jboone's updated sampler branch. 2020-06-25 21:01:35 +02:00
Jared Boone
db2ab8841a Update Sampler.v, moving clock domain crossing to FIFO interface.
Hopefully, I unscrewed the tab/space and line ending mismatches to minimize the diff.
2020-05-30 21:31:17 -07:00
David Given
adba93ae0a Merge pull request #163 from davidgiven/brother120
Untested Brother 120kB write support.
2020-05-24 01:32:28 +02:00
David Given
98587d04a7 Merge from trunk. 2020-05-24 00:56:17 +02:00
David Given
0051b64648 Merge pull request #167 from vanbogaertetienne/trs80fix
Typo fix in FM_TRS80DAM2_PATTERN
2020-05-24 00:47:12 +02:00
vanbogaertetienne
603009ba15 Typo fix in FM_TRS80DAM2_PATTERN 2020-05-22 20:46:48 +02:00
Jared Boone
adb9809692 Simplify Sampler. 2020-05-20 11:34:29 -07:00
David Given
06eb10d2a0 Merge. 2020-05-16 10:38:17 +02:00
David Given
2244299bd9 Add a bias parameter to allow the entire Brother format to be moved around on
the disk.
2020-05-16 10:37:48 +02:00
David Given
6ca06ecafb Fix several embarassingly stupid bugs in the brother 120kB encoder code path. 2020-05-14 10:41:25 +02:00
David Given
9a5958f80b Prevent OOB when appending no bytes to a fluxmap. 2020-05-14 10:40:49 +02:00
David Given
2b53ac057c Fix some bugs which allow erasing tracks with F_FRAME_WRITE_CMD to work again.
(F_FRAME_ERASE_CMD always worked.)
2020-05-13 23:45:58 +02:00
David Given
5deba8af41 Untested Brother 120kB write support. 2020-05-13 14:49:06 +02:00
David Given
3c54a663b8 Merge pull request #157 from davidgiven/amigacorruption
Fix some issues causing corruption when reading Amiga disks
2020-04-09 00:16:38 +02:00
David Given
1fd65452c4 Typo fix. 2020-04-08 23:37:08 +02:00
David Given
30646ccb07 Fix an Amiga decoder bug where truncated sectors would be considered valid (the
Amiga checksum algorithm is weak and zero bytes don't contribute to the
checksum).
2020-04-08 23:35:55 +02:00
David Given
5be7249a30 Merge pull request #155 from davidgiven/amigawriter
Fix stray bytes at the end of images
2020-04-07 23:13:23 +02:00
David Given
067af18103 When writing images, use the sector size in the spec rather than the actual
data size, to avoid problems with multipart formats like the Amiga.
2020-04-07 23:02:47 +02:00
David Given
8dbd2a72a7 Merge pull request #150 from davidgiven/sixbit
Fix the new sampler and sequencer
2020-04-03 23:54:29 +02:00
David Given
c29e131a3b Convert the IBM format back into a unicorn now I've fixed it. 2020-04-03 23:49:01 +02:00
David Given
a9e30c1e49 Fix an off-by-one error in the sequencer that should have it generating correct
sequences.
2020-04-03 22:58:51 +02:00
David Given
972c8c6b61 Fix off-by-one sampler error, so now the clock rates are right again. 2020-04-03 22:27:33 +02:00
David Given
2007ff7546 Fix merge wibble. 2020-04-03 21:49:26 +02:00
David Given
64694580cd Remember to bump the protocol number after the bytecode change. 2020-04-03 21:46:51 +02:00
David Given
deaab94494 Merge pull request #146 from davidgiven/sixbit
Switch to a simplified encoding with a six-bit timer.
2020-04-03 00:45:21 +02:00
David Given
1509e1f89d Document the new bytecode format. 2020-04-03 00:38:20 +02:00
David Given
29e1ddc2ff Bytecode upgrades always produce the latest version; we don't want to upgrade
1->2->3 (although that specific case is harmless, by accident).
2020-04-03 00:36:55 +02:00
David Given
1fe6434563 Something is wrong with the IBM PC writer, I don't know what. Mark it as a
dinosaur again.
2020-04-03 00:27:12 +02:00
David Given
0367b7e77d Merge from trunk. 2020-04-01 00:06:35 +02:00
David Given
e6da85bf64 Merge pull request #145 from davidgiven/writereport
Add a machine readable read report.
2020-04-01 00:04:54 +02:00
David Given
cd19fcdadd The CSV report now writes records for every sector in the output map, even the
missing ones.
2020-03-31 00:14:23 +02:00
David Given
1954f02cfb Don't reset the device on startup because it confuses Linux. 2020-03-30 22:23:18 +01:00
David Given
39b23200b0 Fix missing flag dependency. 2020-03-29 23:12:12 +02:00
David Given
0644d6d965 Remove some stray tracing (which was causing problems). Fix a potential problem
where sampleclock posedges could be lost in the sequencer.
2020-03-29 23:11:53 +02:00
David Given
a075694d8e Rewrite the sequencer to work with the new six bit bytecode. Fiddle with the
USB stuff a lot in an attempt to resolve the weird packet loss issue.
2020-03-29 15:10:35 +02:00
David Given
b1ea5a9a35 Rework the writer to use a fluxsink rather than just writing stuff directly. 2020-03-29 15:08:45 +02:00
David Given
00087cbb6b Fix a catastrophic DMA setup bug which was causing (probably) every other byte
of data to be mixed up with every other byte... but as every other byte was a
0x80 we never noticed up until now.
2020-03-20 00:06:58 +01:00
David Given
1b48ea20c4 Remove the cruncher. 2020-03-20 00:06:07 +01:00
David Given
3d0f019fc4 Replace the sampler with one using the new simplified bytecode. 2020-03-19 23:39:23 +01:00
David Given
a08bfc183f Display the tick value along with each interval in the histogram. 2020-03-19 22:16:07 +01:00
David Given
c5aef9b051 Annotate inspect to display USB bandwidth. 2020-03-15 13:47:17 +00:00
David Given
fc2655ecd6 Rework the bytecode format to use a much simplified setup: a six-bit timer with
the top two bits reserved for pulse and index state. This is actually smaller,
bandwidth-wise, than the old version, and may be smaller than the crunched
version.
2020-03-14 18:58:43 +00:00
David Given
a737c723d3 Make sure to update before installing packages. 2020-03-14 14:47:04 +00:00
David Given
37aa8b62b0 Add a --write-csv=X option to the reader to dump the sector status map as a
machine-readable file.
2020-03-14 14:35:19 +00:00
David Given
a401173f6d Teach the Amiga decoder how many sectors to expect on each track. 2020-03-09 12:54:29 +00:00
David Given
ce76dc4279 Merge pull request #140 from davidgiven/sectors
Fix a couple of annoying but minor issues
2020-02-28 00:08:11 +01:00
David Given
1025bd857b Don't crashloop if the USB's not connected, as it causes the drives to be
constantly reprobed (which runs the motor).
2020-02-27 22:32:27 +01:00
David Given
025802b2d0 Count required sectors correctly on mac disks. 2020-02-27 22:30:05 +01:00
David Given
adbcb2cd31 Merge pull request #139 from davidgiven/sectors
Add support for required sectors, drive autodetection and fix homing on 8" drives.
2020-02-24 21:55:27 +01:00
David Given
c47a563790 Don't seek to track -1 on homing (it appears to upset 8" drives). Detect which
drives are present, so that if only a single drive is attached then it's always
track 0, regardless of which connector it's on.
2020-02-24 21:47:40 +01:00
David Given
04c09d1a5b Hopefully, fix the problem where ^Cing a job gets the board in a confused
state.
2020-02-21 22:16:20 +01:00
David Given
323da8272a Hopefully add support for giving the reader a set of required sectors, so if
one is missing then we can tell and the track can be reread.
2020-02-21 22:14:44 +01:00
David Given
38700c79fc Merge pull request #137 from davidgiven/docs
Update documentation.
2020-02-20 00:32:19 +01:00
David Given
d504d1890a Remember to document that you need a FDD cable. 2020-02-20 00:30:17 +01:00
David Given
d53e757cfb Rework some of the Brother documentation. 2020-02-20 00:25:55 +01:00
David Given
4983239458 Rework the hardware and software documentation. 2020-02-20 00:17:16 +01:00
David Given
376985828a Add the ditaa pinout table. 2020-02-19 23:49:43 +01:00
307 changed files with 71551 additions and 1752 deletions

View File

@@ -1,6 +1,7 @@
version: '{branch}.{build}'
clone_depth: 1
skip_tags: true
image: Visual Studio 2019
environment:
MSYSTEM: MINGW32

View File

@@ -10,7 +10,7 @@ jobs:
with:
fetch-depth: 1
- name: apt
run: sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build
run: sudo apt update && sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build
- name: make
run: make

View File

@@ -1,252 +1,252 @@
:400000000080002011000000D5110000D5110000064A08B5136843F020031360044B1A6803F53F5302331A6001F0F2F8E8460040FA46004010B5054C237833B9044B13B16F
:400040000448AFF300800123237010BD6881FF1F00000000503A0000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF00000000B7
:400080006C81FF1F503A0000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1F32
:4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F000080024B012200205A7293
:4001000002F02CBA8881FF1F10B5C4B2204601F041FA0128FAD110BD08B572B60F4B0F49DA680132DA601A690132C82A08BF00221A615A6918690132A72A08BF00224A6104
:400140005B69002B0CBF02230023002814BF184643F0010002F06AFF62B608BD8881FF1F10B504460D4B8278997E91421CBF00225A7702689A610279094B1A718378002B93
:4001800014BF0220012002F015FFE07802F00CFF2079BDE8104002F043BF00BF8881FF1FA081FF1F70B5C4B220460E4601F0FAF9314605460246204601F0B6FA204601F086
:4001C000E9F90128FAD0284670BD000038B50B4CA57F5DB904F11800FFF7C2FF012002F053F94FF47A7002F065FB6577E36823620123A377BDE8384002F09ABB8881FF1FFA
:4002000038B50446C5B2284602F04AF9062002F067FB44F00200C0B202F042F9062002F05FFB284602F03CF9BDE83840062002F041BB10B5642402F02DF920B10120BDE8EA
:400240001040FFF7DDBF0120FFF7DAFF013CF2D1F4E7000038B5044D0024285D013402F0EFFA402CF9D138BDAC81FF1F08B502F009FD002002F012FD02F024FD02F02EFD5E
:4002800080B208BD10B50446012002F021F9642002F010FBFFF7EAFF2080002002F018F9642002F007FBFFF7E1FF608010BD08B502F014FE002002F01DFE02F02FFE02F0EE
:4002C00039FE80B208BD10B50446FFF7B2FF322002F0F0FAFFF7EBFF20800020FFF790FF322002F0E7FAFFF7E2FF608010BD0FB400B593B014AB53F8042B402102A801938B
:4003000002F08EFF02A802F030F902F03AF913B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF7EFFE62782146BDE81040042001F086B9643A000007B5002324
:40034000ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB0000F8B51D4C0646FFF733FF637F03B156B91A48FFF7BEFFFFF75EFF012000236077636602F045
:40038000AFFA3246616E1548FFF7B1FF114D0027636E9E4216D002F07DF800B16F66636E9E4205DD0020FFF72BFF6B6E013305E005DA0120FFF724FF6B6E013B6B6602F08B
:4003C000B7FAE5E7322002F075FABDE8F8400448FFF78DBF8881FF1F713A0000783A0000953A00002DE9F04F9BB062B602F00AFB8A49042002F02EFB894802F057F889486B
:4004000002F0FAFD884802F08BF802F0DBFC02F0ADFB002002F0CEFD02F0A6F80221002001F06EF8814D0321084602F061FAAA462C4602F07DFAAB7F73B12A6AEB689B1AE2
:4004400041F28832934207D9002002F01DF8002002F0B0FD0023AB7701F08AF818B97448FFF745FF04E001F089F80028F7D109E001F07EF80028FBD06E48FFF738FF0320E6
:4004800001F0A6F9032001F085F80128D1D16A48FFF766FE69490320FFF784FE94F868106748FFF724FF94F86830023B142B00F26A84DFE813F0150068041E0068042400B2
:4004C0006804480068046B006804D1006804F9016804A9036804C9036804CF036804DA0303238DF828308DF829300C238DF82A30B7E394F86A00FFF731FF524BAEE3FFF72E
:4005000065FE00236372E068627A02F0FF0132B9EB681B1AB3F57A7FF6DD0B460AE04BB100228AF80920DAF80C10627A12B9EB685B1AFAE707228DF8282004228DF8292037
:40054000ADF82A308DE30220FFF7DEFD00270DF1280902F0EDF94FF480780026C8EB07039A1906F809200136402EF9D10220FFF7CBFD32464946022001F064F8B8F101087C
:40058000EBD10137402FE4D12F4B42E04FF00109002702F0CDF94FF00008012001F018F9012000F0F7FF0128FAD10DF1280B4022594601F0B9F8012000F0ECFF0028FAD137
:4005C000064608EB07030593059B1BF806203344DBB2934209D08DE80C003946334642461A48FFF784FE4FF000090136402EEBD108F10108B8F5807FCFD10137402FC8D17D
:4006000049461348FFF773FEB9F1000F00F05381104B1B8809A8ADF8243023E319010000F900000091000000C50000008881FF1FA33A0000B63A0000A081FF1FF081FF1F13
:40064000C03A0000543A0000563A0000CF3A0000EB3A0000583A000094F86A0001F038FF606EFFF77BFE02F047FD944B944F1A78002602F0FB021A701A7842F001021A70CD
:400680001A7802F0FE021A701A7802F0FE021A7002F036FD0220FFF737FD41F6FF734FF480420121022002F08BFC84F8A80002F0ADF8B8550136402EF9D1DFF82482002668
:4006C00008F18D0B1FFA8BF70136402E14BF3246002218F8010F2244062392F82420402102F0C8F83A4646F2434198F8000002F0D3F84037402EBFB2E6D19AF86B3043B175
:4007000000238AF80930637A002BFCD000238AF80930182200210AA802F04EFD694B4FF0FF320C9340230D930023236062602372236894F8A800234493F8241002F01EF82F
:4007400094F8A80001F0DCFF012194F8A80001F0AFFF2368002BFCD000239946CAF80430DAF80C200127059202F0E2F8059AE3689B1AB4F86C2093420ED36FB1042195F822
:40078000A80002F007F894F8A80002F013F80028F9D107468AF80800237A03F0FF08002B48D16A682B689A4202D1002FDCD141E063680AA80BEB831343440A93C8F1400391
:4007C0000B9300F0F9FA0B9B09F10109C3F1400398440D9B5FFA88F8E3B93B4E0220FFF793FCA6F1400EBEE80F000FC6BEE80F000FC6BEE80F000FC69EE80F0086E80F0019
:40080000A6F130014022022000F01CFF703E40230C960D93B8F13F0FCAD962682B4B01321340002BBEBF03F1FF3363F03F030133636099E70AA8267A00F014FB0220FFF76B
:4008400063FC0D9BF6B2402B07D0022040221E4900F0F8FE0220FFF757FC0D9B022033F040021DBFC3F1400292B21749114600F0E9FE0220FFF748FCFFF7ECFC36B11448FB
:40088000FFF735FD0220FFF759FD06E0114B09A81B88ADF82430FFF73FFD627A4946237A0D48FFF724FD71E20C48FFF720FDE66E16F03F0616D0032066E200BF93640040CD
:4008C000AC81FF1F3892FF1F7892FF1F3F000080F53A00005A3A00000F3B0000223B0000AB81FF1F012001F0F9FD95F86A0001F0EFFD02F001FCBA4BB94A1B78B94F43F089
:4009000004031370137843F001031370137803F0FE031370137803F0FE03137002F0F0FB686EFFF71BFD01214FF4804341F6FF72084601F0D9FD85F8A80001F067FFB855B5
:400940000136402EF9D1DFF8BC82002708F18D039EB207930137402F14BF3A46002218F8010F2244052392F82420402101F082FF314646F2475298F8000001F08DFF403623
:40098000402FB6B2E6D1DAF86C3000269B09182231464FF0FF3B0AA8CAF800600593CAF804B0B1468AF80860B04602F005FC0D973746012000F00CFF069601F0B9FFB8F170
:4009C000000F0AD14EB9012000F0E4FD012804D14022854900F0A8FE06462268834B01321340002BBCBF03F1FF3363F03F036168B8BF01338B4200F09180069B3BB1237A59
:400A0000002B40F09C806B7A002B40F098800B9BBBBBB8F1000F09D0754A7F2199540133402BFBD1724A0B930A922AE04EB3012000F0B0FD28BBDFF8B8E13F2E0EF1400CB9
:400A4000BCE80F00AEE80F00BCE80F00AEE80F00BCE80F00AEE80F009CE80F008EE80F00AEF130030A9307F101070B9607DD059BBB4204D0012000F0ABFE464601E04FF08B
:400A800001080B9BDBB12368079A0AA802EB83120D9BC3F1400313440C9300F0F2F90D9B6BB92A68514B01321340002BBEBF03F1FF3363F03F030133236040230D936368C3
:400AC00001332BD12B683F2B28D14FF0000BC5F804B001F037FD85F808B06B6895F8A8002B4493F8241001F049FE95F8A80001F007FE012195F8A80001F0DAFD85F809B0CD
:400B0000637A002BFCD04FF0000B01208AF809B001F024FD584601F0E1FC01E0069B2BB1237A63B96B7A53B90123069363685B453FF443AF09F10109D5F804B03DE76168F6
:400B40002C482268FFF7D3FB01F002FD012001F0C5FC002001F002FD042194F8A80001F019FE94F8A80001F025FE0028F9D19AF8A80001F0B3FD9AF809309AF80820029350
:400B8000012303920193CDF800804B463A4605991948FFF7ACFBB8F1000F16D1059BBB420AD0012000F0F6FC01280646F6D10E49FFF7F8FA3F2803DC012000F01DFE04E00C
:400BC000304600F005FE0137E8E7FFF743FB0B48FFF78DFB237A0BB10220D5E0084B18E597650040AC81FF1F7892FF1F3F0000803892FF1F2C3B0000373B0000673B00002F
:400C00005C3A0000AB81FF1F94F86A0001F060FC606EFFF7A3FB6148FFF769FB00236372637A002BFCD0012001F098FC00238AF80930637A002BFCD0002001F08FFC5848CC
:400C4000FFF755FB574B09E000206077FFF786FB554B03E05548FFF783FA554B1B88ADF828300AA8FFF758FB90E0A37F3BB1002001F00AFC002002F09DF90023AB7702F0F3
:400C80001FF9002002F0C2F82A2601F0EDFF002001F090FF324600210AA802F08DFA17238DF828308DF8296001F042FE002001F0EBFB002002F07EF9C82001F0FBFD0DEB20
:400CC0000600FFF7DFFA0DF13E00FFF7FCFA01F02FFE012002F06EF9322001F0EBFD0DF12E00FFF7CFFA0DF14200FFF7ECFA012001F0CAFB4FF4967001F0DCFD01F018FE3C
:400D00000DF13600FFF7BEFA0DF14A00FFF7DBFA002001F0B9FB4FF4967001F0CBFD01F007FE022002F046F9322001F0C3FD0DF13200FFF7A7FA0DF14600FFF7C4FA0120CB
:400D400001F0A2FB4FF4967001F0B4FD01F0F0FD0DF13A00FFF796FA0DF14E00FFF7B3FA002001F091FB4FF4967001F0A3FD01F0DFFD002002F01EF90023637702F022F8F9
:400D800001F0F4FE6DE70120FFF7D8FA032000F01FFD0848FFF7ABFAFFF74BBB763B0000843B00005E3A0000603A0000F081FF1F623A0000913B000070B50024012542684B
:400DC000002A4ED0C368002B4BD00368013A591C01601B784260802B01D145752FE013F0800F467D0269017D12D036B1D20042F004020331026101754475026903F001030A
:400E0000D20042F004021A43037D0261033315E046B13F2B06D9D20042F004020331026101754475026943EA0223427D036112B143F0C0030361037D447508330375037DC4
:400E4000072BBCD90269083B22FA03F38268511C81601370C368013BC360037D083B0375ADE770BD07B5027D42B102AA002102F8011D026001224260FFF79EFF03B05DF8D5
:400E800004FBF0B5012100244368002B43D0C268002A40D0427D4AB183685A1C8260827D1A70C3684475013BC360EDE7027D072A0BD806680769751C05603578013B45EADF
:400EC00007250832056143600275027D0369A2F10805EB40DBB203F0C006802E07D0C02E0ED103F03F0383754175802308E0C3F3401363F07F03033A03F08103027502E065
:400F00000575002BC0D08268551C85601370C368013BC360B8E7F0BD2DE9F04172B6884B61221A70A3F5F06301221A801924854A9C7092E803008033062283F8002283E874
:400F40000300522203F580731A707F4B7F4A1B787F4EDBB2137040F618027E4B00251A8041F2512223F8022C33784FF4F07003F0010343EA450502F0B7F8013C05F0030524
:400F80002ED0032DF0D1744B4FF480721A8007221A70724A002548211570917002221D705D7103F8032C0422DA716D4A6D4C13786D4E43F00103137012F8013C062743F000
:400FC000030302F8013C2378012243F0800323705B4B1A70654A137843F02003137000E0FEE707FB056300219A881868013502F0E3F8072DF5D15E485E4E002550F8041F99
:4010000005F1105303F1520221F0FF075333C9B20B4452005B0002329A4206D012F802EC12F801CC0EF807C0F5E7B0420D44E5D1514A002313609360136193614F4B504FDF
:401040001A68504BDFF888811A604F4B1A684F4B1A604F4A137843F002031370137C43F0020313742378A2F5863243F040032370413A137843F010031370464A464B07CAE8
:4010800003C31A80454A2833106843F8250C127903F8212C424A07CA03C31A80414AE83B07CA03C31A80404A083307CA03C31A803E4A3F4BA2F5616203CBC2F8100EC2F8D1
:4010C000141E1378042043F008031370394B02F5AA521B783D78DBB298F80060EDB203F007010C321B091170F6B2537045F003033B7046F0030388F800302F4B48221A70EA
:401100002E4A402313702E49937013729372082382F81F3220220A7048710A72294A0A20137001F0DDFB284B88F8006044223D70264D1A7094E80F0007C52B80BDE8F08102
:40114000004800404C0F00480F010049A146004025420040224200400440004006400040A2430040A0430040963B0000E8460040FCFFFF47A000004800760040540F00485E
:40118000F846004020760040580F004828760040035001400C0F0048C0510040180F0048200F00482C0F0048380F004832510040440F0048CF0100491D510040015900404F
:4011C000235B0040585B004076580040B0430040F946004008B501F0C3FF03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC086005E001F0B2FF0C230360FE
:401200004FF0FF33184608BDCC80FF1FC893FF1F80B51148114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7114653F8046C8C1AA64202D05F
:4012400041F8045BF9E701381033E5E701F08EFFFFF7C8F8FEE700BF01000000683D0000124A134B10B51A60124A134C1368134843F4007313600023032B98BF54F8232052
:401280004FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF73BFEBDE8104001F0EDB900BF0004FA050CED00E014ED00E0000000000080FF1F2B
:4012C000D5110000BC760040C080FF1F08ED00E0F8B501F011FF4B4A01271378022643F001031370137C484C43F001031374474B02F5E3521F700B3203F8946C137805464F
:4013000003F07F031370002001F0EAFA2378404A03F0F90323701378384603F0DF03137023783B43237001F0DBFA282001F0D8FA384B30461A7802F07F021A701A7802F02F
:40134000BF021A7023783343237001F0C9FA2378314A43F0040323700023137053702F4AFF2199540133092BFBD1284601F0C8FE0721172001F0FCFA2949172001F0EAFADB
:401380000721182001F0F4FA2649182001F0E2FA0721152001F0ECFA2349152001F0DAFA0721052001F0E4FA2049052001F0D2FA0721062001F0DCFA1D49062001F0CAFA23
:4013C0000721084601F0D4FA1A49072001F0C2FA0721082001F0CCFA1749082001F0BAFA0021162001F0C4FA1449162001F0B2FA07210C2001F0BCFABDE8F84010490C20BA
:4014000001F0A8BAA5430040944300409D60004012600040F851004084600040ED92FF1F9F1C0000D91A00009D1C0000D11B0000FD1B00002D1C0000651C0000A51C0000EB
:40144000191D0000214B224A10B5187000231370204A40201370204A0F2413701F4A13701F4A13701F4A13701F4A13701F4B4FF400021A604FF080721A604FF400121A60AB
:4014800020221A601860802018604FF480701860174804704FF480001860164B1A70933B19B91A7802F0FE0202E01A7842F001021A70114B03221A70802203F8202C0120D0
:4014C00001F012FE0D4B04221A7010BD0893FF1F0E93FF1F0C93FF1F0D93FF1F0993FF1FF892FF1F0B93FF1F8093FF1F00E100E09E6000409C60004028600040126000401F
:4015000070B5074C054623780E461BB9FFF7E0FE0123237031462846BDE87040FFF792BFB892FF1F0A4A002313700A4A13700A4A13700A4A13700A4A13700A4A13700A4A30
:4015400013700A4B03221A70802203F8202C70470E93FF1F0C93FF1F0D93FF1F0993FF1FF892FF1F0B93FF1F8093FF1F28600040014B1878704700BF0D93FF1F044B1A7802
:4015800002F0FF001AB118780022C0B21A7070470C93FF1F024A0C2303FB0020407870471493FF1F431E072B0CD8074A064B00010344805C5B7800F00F0043EA00200238EA
:4015C00080B2704700207047FC5F00401A4A38B50C2303FB00231B79090C13F0800F00F1FF35044619BF8AB24FF480438BB24FF48042032D18D8DFE805F002070C110021C6
:40160000084601F01BF80DE00021084600F0FAFF08E00021084600F0D9FF03E00021084600F0B8FF054B1855EDB2072D03D801F0EDF8034B185538BD1493FF1FE492FF1FB1
:40164000ED92FF1F431E072B2DE9F0470446894615465CD82F4F0C2202FB0072D388DFF8B8A09BB2C3F500739D424FF00C0303FB007388BFD588DB7884BFC5F50075ADB2C2
:40168000254A43EA15230601B354B244EBB28AF80130224B1A5C9846FF2A01D1FFF796FF0C2303FB047200215170B9F1000F28D03DB31B4F385D01F011F811232946FE22D9
:4016C00018F8040001F0D6F806F5C04278321FFA89F118F8040001F0DFF8124D18F80410385D01F04BF80121385D00F0E1FF735D43F002037355735D03F0FD037355BDE82E
:40170000F08703FB04746379DBB28AF80230BDE8F08700BF1493FF1FFC5F0040ED92FF1FE492FF1F706000402DE9F047044615468846002940D0431E072B3FD8FFF732FF59
:40174000A84203D22046FFF72DFF05461D4E335DFF2B03D141462046FFF738FFDFF868A027011AF8040000F0B9FF1223FE222946305D01F07FF807F5C0411FFA88F278310D
:40178000305D01F089F8DFF84490315D1AF8040000F0F4FF01211AF8040000F089FF17F8093043F0020307F8093017F8093003F0FD0307F8093002E00D4600E00025284675
:4017C000BDE8F087ED92FF1FE492FF1F70600040431E072B0AD8064A0C2303FB002300225A705A79034BD2B200011A54704700BF1493FF1FFE5F0040431E072B9FBF024B61
:40180000000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB21380194A00231488D8B2A4B27CB1082B0CD050680078C0B2E85450680133013050601088E4
:40184000013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F080032B700F232370022301E0022323701370094B1870087030BD00BF8493FF1F8093FF1F18
:4018800000600040FC92FF1FF992FF1F0E93FF1F0A93FF1F8193FF1F074B02221A70074B80221A70064B0F221A70064A00231370054A0120137070470E93FF1F0A93FF1FE3
:4018C000F992FF1F8093FF1F8193FF1F30B5164B16491B780A8803F00F03023BDBB21A4492B20A80124C134A0020118889B279B173B15568215C013BC9B229705168DBB24A
:401900000131516011880130013989B21180ECE7094A1370094A137883F080031370084B0B221A7030BD00BF296000408493FF1F00600040FC92FF1F8193FF1F0A93FF1F07
:40194000F992FF1F064A06231370064A01201370054B80221A70054B00221A70704700BF0E93FF1FF992FF1F0A93FF1F8193FF1F054B9A683AB19A68044910709A680988EC
:40198000518000229A607047FC92FF1F8493FF1F08B5124B1A78D2B21A701B78DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F06003202B05D0402B06D043B99A
:4019C00000F012FC04E001F09FFB01E000F046FD10B9034B03221A7008BD00BF28600040F992FF1F0060004008B5084A084B0120197813880B449BB21380064B00221A7030
:401A0000FFF7B6FF044B03221A7008BD8493FF1F8093FF1F0E93FF1FF992FF1F08B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE80840FFF7D8BFBDE80840FFF746BFB9
:401A40000320FFF795FF034B03221A7008BD00BF0E93FF1FF992FF1F08B5054B002201201A70FFF785FF034B03221A7008BD00BF0E93FF1FF992FF1F08B50A4B1A7832B10C
:401A80001A78094942F080020A7000221A70074B002201201A70FFF76BFF054B03221A7008BD00BFF892FF1F086000400E93FF1FF992FF1F074B1B78DBB2042B05D0062B07
:401AC00005D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF70470E93FF1F38B51D4C2378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF174B1B78190609D538BD5A0620
:401B000002D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B1B7813430F4A13701278934211D10A4A0849154613782078DBB2000605D41378DBB20B70F1
:401B40000B7803F00F0328788342F1D138BD38BD28600040F992FF1F0A93FF1F8193FF1F29600040054A00231380054A916819B191680B7092685380704700BF8493FF1FA2
:401B8000FC92FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4B00221A70FFF7E0FF094AD1799379028843EA012392B2934238BF0380FFF728FE012008BD64
:401BC000FC92FF1F0E93FF1F0A93FF1F00600040084B01221A700F3B9B7C074B1A7B02F00302012A1EBFDA7B82F08002DA7301225A7370470B6000401493FF1F094B0222B3
:401C00001A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7601225A76704700BF0B6000401493FF1F0B4B04221A700F3B93F83230094B93F8242002F043
:401C40000302012A1EBF93F8272082F0800283F82720012283F82520704700BF0B6000401493FF1F0B4B08221A700F3B93F84230094B93F8302002F00302012A1EBF93F8FC
:401C8000332082F0800283F83320012283F83120704700BF0B6000401493FF1F7047FFF741BC0000F0B5184B184E19780C27C9B201234FF0000C31B3CA0720D5144A4FEA33
:401CC000031E7244947850782040C5070DD507FB03652C79240608D5147804F0FE0414706D790C4CEDB204F80E50840706D507FB036425792D0658BF84F801C090700133B0
:401D0000DBB24908D7E7F0BD9F6000401493FF1F70600040FE5F004000F0ACBC70B50446184B88B003AA03F11006154618685968083303C5B3422A46F7D11B782B70FCB1E9
:401D40002223237001AD03232846637000F08AFE002220461146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082AC1700371417100F10400EAD107
:401D800008B070BDC03B00002DE9F0431C4D01222E460C201F274FF0800E4FF0080C194B00FB02581401234418705F70164998F805902144B9F1000F07D098F80440240665
:401DC0004CBF887081F802C001E081F802E000FB0261CC880132E4B29C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D4D1054BFF221A70BDE8F08300BF46
:401E00001493FF1F70600040FC5F00400A600040064B074A1B7802EBC30253681A7C824286BF03EBC0035869002070470893FF1F243C00002DE9F84F424B1A78002A7ED0F1
:401E40001878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF800C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF80420597891425ED19A7893F848
:401E8000039002F07F0206FB02FA05EB0A01CF7093F802B009F0030981F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000F0BDAB9F1010F0CBF4FF0070950
:401EC0004FF00D0981F8059081F801E009E0B9F1010F0CBF4FF005094FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F808A0CAF3072A81F800A0B2F825
:401F000008A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F806A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D288C2F307224A71083394E7BDE81D
:401F4000F88F00BF0D93FF1F1493FF1F0993FF1FFC5F004070600040FA92FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300406908BD0D93FF1F00212DE9D7
:401F8000F84F0B464E4E0C2707FB01F401313219092933554FF000059370494CD3701381937253705371EFD118B1464B1D70464B1D70464B1A78002A7FD0187801250138FD
:401FC000C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4B4FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C36803EB02094B4531D093F802A0D2
:402000000AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B01E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE78BAF1000F06F0030607DA012E7F
:402040000CBF07260D264E7181F8018006E0012E0CBF052609264E7181F801C00833CBE70135092DC3D1C1680A328B1C0A440C200833934209D013F8081C13F80A5C01F05C
:402080007F0100FB01418D72F2E7FFF767FF114B0121186000230C2000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8F84FFFF767BEBDE8F88F00BF67
:4020C0001493FF1FFA92FF1F8293FF1F0D93FF1F0B93FF1F1093FF1F114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F0010191700021D170517841F0B7
:4021000002015170127912F0800F074A1A4414BF8D2389239370FFF715BC0020704700BF006000401493FF1FFC5F004030B4194B1A7902F07F02531E072B27D8164B0C2400
:4021400004FB02339978154D01F0FE0199700021D97029461201505D114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D18C7006E00D2303E0012B0CBFEE
:40218000082309238B7030BCFFF7DCBB002030BC704700BF006000401493FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE43681B798B4201D2012909D800
:4021C000074A0848535CDBB24354A3780120DBB2535410BD002010BD0D93FF1F00600040FA92FF1F8293FF1F38B58A4A8A4C13780021DBB221801806517840F18D800A293D
:4022000000F20581DFE811F05D00030103010301030103010B0003017E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B686360122310E0CB78022B12D12E
:402240008878FFF7E5FD002800F0E180436863606368DA7863689B7843EA02232380BDE83840FFF78FBCCB78032B26D16D4B00228878D5B2854209D3664A91786A4AEE2961
:4022800008BF1346634A917881B106E0187801320028F1D018780344EAE764499278097C914203D16248FFF739FD614B1A78002A00F0AD801A78228018E0BDE8384000F065
:4022C00023BF13F0030313D0022B40F0A0802380504B0C211B7903F07F02564B01FB02339A78554BD2B21A7000225A706360B6E702222280514A11784F4AC9B21170537000
:402300006260ACE7012323804D4BEFE70123238013794C4A1344E9E701390A2977D8DFE801F037764F76067676760A7620009378454ADBB25AE0937803F0FF0153B9404B1F
:402340001A7891425FD01970404B01201870FFF715FE58E0481EC0B2FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB2D2B20A70364A3249D25CCB5C48
:402380009A4240D0314B01221A70FFF753FD3AE003F00303012B2BD009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012B2BD1214A137803F0FD0315E0C0
:4023C00003F00303012B13D008D3022B1FD1114B9B78E3B9BDE83840FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A795AB998781B791749DBB2CA5CC8
:4024000022EA0002CA54BDE83840FFF79BBA002038BD00BF00600040FC92FF1F0893FF1F243C0000883C0000103C0000FB3C0000A093FF1F1493FF1FB992FF1F0B93FF1F4D
:402440000D93FF1FFA92FF1FF892FF1F0C93FF1F0993FF1F8293FF1F0F93FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A80FFF786BB002070470060004007
:40248000FC92FF1FE83B0000014B1870704700BF7F640040014B1878704700BF69640040014B1870704700BF78650040064A0123136002F688321268E0211064034A1170C4
:4024C000A2F540721360704780E100E000E400E0014B1870704700BF72640040014B1870704700BF7665004073B515461E460B4C05230022019200920A460146184623706A
:4025000000F064F932462946207800F01FF90221207800F009F9207802B070BDD080FF1F064A0423136002F688321268E0219064034A1170A2F202321360704780E100E029
:4025400002E400E0014B04221A60704700E100E0014B04221A60704780E100E0014B1870704700BF78640040704738B505460078012428B100F060FD285D0134E4B2F8E706
:4025800038BD08B50D2000F057FDBDE808400A2000F052BDF7B516461F460B4C00230325019300930A4601462846257000F00EF93A463146207800F0C9F80221207800F030
:4025C000B3F8207803B0F0BDE080FF1FF7B516461F460B4C00230225019300930A4601462846257000F0F2F83A463146207800F0ADF82946207800F097F8207803B0F0BD6F
:40260000E180FF1FF7B516461F460B4C00230125019300930A4601462846257000F0D6F83A463146207800F091F80221207800F07BF8207803B0F0BDE280FF1F73B515466E
:402640001E460B4C0023019300930A4601461846237000F0BBF832462946207800F076F80221207800F060F8207802B070BD00BFE380FF1F024B1878C0F38010704700BFFD
:402680008F450040074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFE480FF1FF87B00400078004017280FD8084B0001C25C11B142F0200204
:4026C00001E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001C25C02F0FE02C254C25C02F0DF02C25400207047012070471070004028
:4027000017280DD8074900010B4603441A7942F004021A71435C43F00103435400207047012070471070004017280BD8064A0001835C490003F0F10301F00E0119438154A7
:4027400000207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBFC00000F1804000F5EC4081809ABFC280002001207047000017289FBF73
:40278000034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBF1143195400200120704700BF1470004017289FBF034B0001185C00F051
:4027C000070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC44D2B222709DF8082003F00F0343EA0213DBB263709DF80C30002003F08F
:402800000F03A370E07010BD012010BD10B500F073FC0A4A5378182B0AD91478013B5370E30003F1804303F5F0431B78137000E0FF2400F065FC204610BD00BFE480FF1FD1
:40284000030610B5044611D400F056FC084AE300117803F1804303F5F04319705378147001335370BDE8104000F04ABC10BD00BFE480FF1F30B504060CD411F4704509D14E
:40288000C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5F04081805ABFC280002001207047000038B50446084DB4F5004F05D98C
:4028C000286800F011FCA4F50044F6E7034B58686043BDE8384000F007BC00BFEC80FF1F024B1B7A584300F0FFBB00BFEC80FF1F0E4B00F003001A78490102F0FC021043EC
:4029000018701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F010021A70704700BF83430040014B01221A70704784430040044B00F090
:402940000F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230042F82310704700BF08ED00E000F01F0000F16040490100F56440C9B29F
:40298000017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72DB68B3FBF2F3084A1360084B4FF400421C60C3F887
:4029C000E82010BDBC92FF1F312A000010E000E0EC80FF1F14E000E018E000E0024A136843F002031360704710E000E008B5FFF7F5FF034A136843F00103136008BD00BF9F
:402A000010E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BFBC92FF1F024B1868C0F30040704700BF10E000E038B5FFF7F5FF012808D1054D002455F859
:402A4000243003B198470134052CF8D138BD00BFC092FF1F024B03EB8003586859607047BC92FF1F134B144A1B78DBB20360127843EA0223114A0360127843EA0243104A93
:402A80000360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA02430A4A4360127843EA02634360704700BF0301004904010049EC460040B6
:402AC000020100490101004900010049050100490601004910B500F00FFB204A044613780A2043F002031370137C43F00203137412F80A3C43F0010302F80A3C937943F01F
:402B00000103937102F5AB52137843F003031370134B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222183B1A70094A19
:402B4000137843F008031370FFF7CAFE064B10222046BDE810401A6000F0D2BAAB4300400E5900402F5B004080E200E008B500F0C3FA0F4A137803F0FE031370A2F5AA523E
:402B80001D3A137803F0FD031370137C03F0FD03137412F80A3C03F0FE0302F80A3C937903F0FE039371BDE8084000F0A9BA00BF08590040044A137803F03F0343EA8010C1
:402BC000C0B21070704700BF08590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210736D
:402C00004B4341F2883103F6C41393FBF1F305490B60054B1A8070470A590040D23B00008A93FF1F8C93FF1F9093FF1F08B5102000F0A6F907210420FFF79AFE074904204B
:402C4000FFF788FE064A0C20137843F006031370FFF7BCFF034B00221A8008BD252D0000095900408893FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF72ABF84
:402C8000D892FF1F044B1A7802F0FB021A701A7842F001021A7070470859004010B5084B1C7814F0010403D10028F9D0002404E02046FFF715FE024B1B78204610BD00BFC6
:402CC00009590040034A044B1B881088181A00B2704700BF9093FF1FA25B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FBE0
:402D000000F2022391FBF3F30028D8BF5B42134493FBF1F000B270478A93FF1F8C93FF1F8893FF1F7047000010B500F0E5F9214A044613780A2043F001031370137C43F09E
:402D40000103137412F80A3C43F0020302F80A3C937943F00203937102F5AA521832137843F003031370144B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0215
:402D800003F8012CCE2203F8062CA3F597530222123B1A70094A137843F008031370FFF79FFD074B08222046BDE810401A6000F0A7B900BFAB43004006590040275B004031
:402DC00080E200E008B500F097F90F4A137803F0FE031370A2F5AA52153A137803F0FE031370137C03F0FE03137412F80A3C03F0FD0302F80A3C937903F0FD039371BDE8E0
:402E0000084000F07DB900BF00590040044A137803F03F0343EA8010C0B21070704700BF00590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF20
:402E40000C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A80704702590040DC3B00009693FF1F9C93FF1F77
:402E80009493FF1F08B5102000F084F807210320FFF76EFD07490320FFF75CFD064A0C20137843F006031370FFF7BCFF034B00221A8008BD7D2F0000015900409893FF1F31
:402EC00010B5054C23781BB9FFF7DCFF01232370BDE81040FFF728BFD992FF1F044B1A7802F0FB021A701A7842F001021A7070470059004010B5084B1C7814F0010403D1E6
:402F00000028F9D0002404E02046FFF7E9FC024B1B78204610BD00BF01590040034A044B1B881088181A00B2704700BF9493FF1FA05B00400E4A13881BB223B111880A23E0
:402F400009B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270479693FF1F9C93FF1F9893FF1F7047000060
:402F8000034A00F0F800137803431370704700BF02410040034A00F0F800137803431370704700BF06410040014B1870704700BF76640040014B1870704700BF7C6400403B
:402FC00073B515461E460B4C04230022019200920A46014618462370FFF7F8FB324629462078FFF7B3FB02212078FFF79DFB207802B070BDFC80FF1F074A0223136002F656
:4030000088321268E0215064044A11706FF440710A441360704700BF80E100E001E400E0014B1870704700BF74650040014B1870704700BF77640040FEB5494652465B4644
:403040000EB40746244909688A46244A12682448022100F071F8030020480068C018204900F06AF8143883460121C9430C460125002600F041F8814651460B7823400B7094
:403080005846013000F030F83800F04028400B78234003430B70584600F026F80136072EF2D9002001300138013001200B78234003430B705846043000F016F8484600F0FE
:4030C0001FF800BF00BF00BF0EBC894692469B46FEBD00BFAFF30080D480FF1FF880FF1F00C20100000000000230800803D000BF01380046FCD17047EFF3108072B6704723
:4031000080F31088704700BF094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E0137900207047006000401493FF1F002902D0B0FBF1F039
:40314000704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF6081FF1F0E4B70B51E460E4C0025E41AA410A54204D056F845
:40318000253098470135F8E700F0D4FD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BD403D0000403D0000403D0000483D000003460244934202D071
:4031C00003F8011BFAE7704730B5141E05469BB0184604DA8B232B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029305934FF6FF7300910491ADF80E3002466A
:403200001E9B6946284600F073F8431CBCBF8B232B6014B1009B00221A701BB030BD000007B5009313460A46014603480068FFF7CBFF03B05DF804FB6081FF1F2DE9F04781
:403240008E6882469E420C46914698463ED88A8912F4906F3AD02568096902236F1A656905EB450595FBF3F57B1C43449D4238BF1D4653050FD5294600F04AFB064698B178
:403280003A46216900F0D2FAA38923F4906343F08003A38113E02A4600F098FB064670B92169504600F0E8FA0C23CAF80030A3894FF0FF3043F04003A381BDE8F0872661F3
:4032C0003E44266046466561ED1BA560464528BF464649463246206800F0B3FAA36800209B1BA36023681E442660BDE8F08700002DE9F04F9DB003938B8980461C060D4643
:4033000016460DD50B695BB9402100F001FB2860286118B90C23C8F80030CDE040236B610023099320238DF82930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EBAA
:40334000060910D003E0252BF9D02746F3E74B46324629464046FFF771FF013000F0A780099B4B4409933B78002B00F0A08000234FF0FF3204930793059206938DF85330B6
:403380001A930126052221784E4800F041FA671C049B38B14B4A3C46801A06FA00F018430490EFE7D90644BF20228DF853201A0744BF2B228DF8532022782A2A03D0079A60
:4033C00000210A200BE0039A111D12680391002A10DA524243F00200079204900BE027463B780134303B092B03D800FB02320121F5E701B107923B782E2B1ED17B782A2B3F
:403400000AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E0002319460593781C0A2407463A780130303A092A03D804FB01210123F5E703B10591032239782248C1
:4034400000F0E6F940B14023CBEB000003FA00F0049B013718430490397806221B487E1C8DF8281000F0D4F988B1194B33B9039B073323F007030833039314E003AB0093EC
:403480002A46144B04A94046AFF3008007E003AB00932A460F4B04A9404600F093F8B0F1FF3F824603D0099B5344099342E7AB895B0601D4099801E04FF0FF301DB0BDE802
:4034C000F08F00BF0F3D0000153D0000193D0000000000003D3200002DE9F04791461F460A698B6806469342B8BF1346C9F8003091F843200C46DDF8208012B10133C9F8EF
:4035000000302368990642BFD9F800300233C9F80030256815F0060510D104F1190A07E00123524639463046C04701301AD00135E368D9F800209B1A9D42F1DB94F84330E8
:403540002268003318BF012392060FD5E118302081F843005A1C94F845102244023382F8431003E04FF0FF30BDE8F08704F1430239463046C0470130F4D02268D9F8005010
:40358000E36802F00602042A08BF5D1B2269A3680CBF25EAE57500259342C4BF9B1AED184FF000091A344D4509D00123224639463046C0470130D5D009F10109F3E70020FB
:4035C000BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9B01F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A40F0CA8081F84520834955E0642A1ED03B
:40360000692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B8800A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F14205111D1960136884F84230A8E021683E
:403640001A6811F0800F02D0111D196008E011F0400F02F10401196002D0B2F9003000E01368002B3CDA2D225B4284F8432037E021681A6811F0800F02D0111D196007E0F0
:4036800011F0400F02F10401196001D0138800E01368227E5C496F2A14BF0A2208221BE078225A4984F845202268186812F0800F00F104051D6003D1550601D5038800E0E0
:4036C0000368D00744BF42F0200222601BB9226822F0200222601022002084F8430001E049490A226568002DA56008DB206820F0040020602BB9002D7DD175460CE0002BBC
:4037000079D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D1082A0BD12368DA0708D5236962689A42DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A68FA
:4037400010F0800F496903D0101D1860136808E010F0400F02F104001860136801D0198000E0196000232361754616E01A68111D1960156800216268284600F049F808B1F0
:40378000401B6060636804E004F1420584F8422001232361002384F84330CDF800803B4603AA21463046FFF797FE013002D14FF0FF3026E023692A4639463046C0470130EF
:4037C000F5D023689B0710D5002504F1190907E001234A4639463046C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842B8BF184605E00B7804F1420584F8423091
:403800008AE705B0BDE8F083C03B0000203D000010B5C9B202449042034605D01C7801308C42F8D1184610BD002010BD10B5431E0A44914204D011F8014B03F8014FF8E76E
:4038400010BD884210B501EB020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F8014B02F8014FF8E710BD38B50546002944D007
:4038800051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF18685B681218226063600C6023E0A24203D813465A6820
:4038C000002AF9D118681918A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E021686018824201BF106852680918216062605C6019
:403900002846BDE8384000F098B838BDE092FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C23336046E000F082F8234B1C681A462146A1B10B6883
:403940005B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C23681BB9304600F052F820602946304600F04DF8431CCB
:4039800018D0C41C24F00304A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A304600F034F80130EBD10C233360304600F03EF80020E9
:4039C00070BD00BFE092FF1FDC92FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F885420ED929463846FFF78BFF044650B131469B
:403A00002A46FFF713FF31463846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7DEFB431C02D1236803B12B6038BDC493FF1F7047704751F8040C50
:403A40000028BEBF091851F8043CC0180438704700000000050209020B020D020F021102130215027265706C792030782530327800686F6D696E6700626567696E6E696EEF
:403A800067207365656B2066726F6D20256420746F2025640066696E6973686564207365656B0057616974696E6720666F72205553422E2E2E0055534220726561647900AF
:403AC000636F6D6D616E6420307825303278006661696C2025642B25642B2564203D3D2025642C206E6F74202564007061737365643D256400756E64657272756E2061664A
:403B0000746572202564207061636B65747300636F756E743D256420693D256420643D256400636D645F777269746500646F6E6520256420256400703D25642063723D25BB
:403B4000642063773D256420663D256420773D256420696E6465783D256420756E64657272756E3D25640077726974652066696E6973686564007374617274206572617393
:403B8000696E670073746F702065726173696E670069646C650000510040100040510040300000000140001000140140000800400140000A004C014000020050014020003F
:403BC0003031323334353637383941424344454600000001000000040000001000010000000400000010000028000000000104000100000000000000000157494E555342F2
:403C00000000303030303100000000000000000012034D0053004600540031003000300001000000010000002C3C000001000000FB3C000000000000000000000100000010
:403C4000443C000001000000CD3C000004000000663C0000000000000000000000000000643C0000FF00000001024000FF00000082024000FF00000003034000FF0000002B
:403C800084034000FF00020304030904160346006C007500780045006E00670069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F0096
:403CC0006C006F0067006900650073000009022E0001010080320904000004FF00000107050102400000070582024000000705030340000A0705840340000A12010002FFD7
:403D00000001080912006E0100020180014300232D302B2000686C4C00656667454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E46704759
:403D40005900000061120000F8B500BFF8BC08BC9E46704735000000683D0000C880FF1FA00000006012000000000000C893FF1FFF000000675000400C0000000700000024
:403D8000FFFFFFFF7F8000003F0000000000007D00FA0000400000000090D003FF0000000000000000000000000000000000000000000000000000000000000000000000B0
:403DC0000D3D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000079
:403E00000081FF1F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E3
:4000000000800020110000003110000031100000064A08B5136843F020031360044B1A6803F53F5302331A6001F020F8E8460040FA46004010B5054C237833B9044B13B18B
:400040000448AFF300800123237010BD6881FF1F00000000B8380000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF0000000051
:400080006C81FF1FB8380000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1FCC
:4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F0000800E4BDA681AB901215F
:4001000019745A7410E05A7C1A741A7C0AB1002207E059699A69D8688A1A82428CBF002201225A745A699A611B7C13B1002002F043B970478881FF1F10B5C4B2204601F054
:4001400057F90128FAD110BD08B572B60F4B0F495A6901325A61DA690132C82A08BF0022DA611A6AD8690132A72A08BF00220A621B6A002B0CBF02230023002814BF184660
:4001800043F0010002F080FE62B608BD8881FF1F38B50446C5B2284602F0B0F8062002F0CDFA44F00200C0B202F0A8F8062002F0C5FA284602F0A2F8BDE83840062002F0C2
:4001C000A7BA10B5642402F093F828B9FFF7E0FF013CF8D1204610BD012010BD70B5C4B2054620460E4601F003F9012805D0204601F01CFA2846FFF79FFF204601F000F9AD
:40020000314605460246204601F0BCF9204601F0EFF80028FAD1284670BD000038B5044D0024285D013402F039FA402CF9D138BDAC81FF1F08B502F053FC002002F05CFCBD
:4002400002F06EFC02F078FC80B208BD10B50446012002F06BF8642002F05AFAFFF7EAFF2080002002F062F8642002F051FAFFF7E1FF608010BD08B502F05EFD002002F02B
:4002800067FD02F079FD02F083FD80B208BD10B50446FFF796FF322002F03AFAFFF7EBFF20800120FFF774FF322002F031FAFFF7E2FF608010BD0FB400B593B014AB53F835
:4002C000042B402102A8019302F0DEFE02A802F07AF802F084F813B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF723FF62782146BDE81040042001F0D0B8B5
:40030000CC38000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8643043B1002001F0D8FF002002F06BFD002384F864304E
:4003400010BD00BF8881FF1F38B5104D837895F8672004469A4204D0FFF7E4FF002385F86A302368C5F865302279094B1A71A378002B14BF0220012002F04AFDE07802F02E
:4003800041FD2079BDE8384002F078BD8881FF1FED81FF1F38B50D4C94F8645065B904F16500FFF7D1FF012001F09CFF4FF47A7002F0AEF984F86A506369E366012384F84D
:4003C0006430BDE8384002F0E1B900BF8881FF1FF8B5214C0546FFF7DDFF94F86A3003B15DB91E48FFF767FFFFF7EBFE0120002384F86A00236702F0A1F92A46216F184872
:40040000FFF759FF144E0027236F9D4216D001F06FFF00B13767236F9D4205DD0120FFF7B7FE336F013305E005DA0020FFF7B0FE336F013B336702F0A9F9E5E7322002F047
:4004400067F92A2DCCBF0020012002F023FDBDE8F8400448FFF72FBF8881FF1FD9380000E0380000FD3800002DE9F04F99B062B602F0F6F99D49042002F01AFA9C4801F0D9
:4004800043FF9C4802F0E6FC9B4801F077FF02F0C7FB02F099FA002002F0BAFC01F092FF0221002000F05AFF944C012001F0D2F8002384F86730FFF76DFFFFF782FE84F8A3
:4004C0007400FFF72FFF012384F86730FFF762FFFFF777FE84F87500FFF724FF884B94F87400884994F875202546002A14BF0A461A46002808BF19468348FFF7DCFE032177
:40050000084602F023F9264602F040F994F8643043B1EA6E6B699B1A41F28832934201D9FFF700FF00F052FF18B97848FFF7C3FE04E000F051FF0028F7D10BE000F046FF85
:4005400010B902F023F9F9E77148FFF7B4FE032001F06CF8032000F04BFF0128D4D16D48FFF7F2FE6C490320FFF738FE94F876106A48FFF7A0FE94F87630023B142B00F229
:40058000D483DFE813F01500D2031E00D2032400D2034F00D2037500D203D700D203BF01D2030603D2032A03D2033103D2034B0303238DF820308DF821300F238DF8223084
:4005C00028E394F87800FFF703FF554B1FE3FFF7E1FE002323746069227C02F0FF0132B96B691B1AB3F57A7FF6DD0B4611E083B10022174696F878107069277494F810E007
:40060000BEF1000F02D16B691B1AF7E701329142F3DA07228DF8202004228DF82120ADF82230F7E20220FFF787FD4FF000080DF1200A02F0ABF84FF480790027C9EB080303
:40064000DA1907F80A200137402FF9D10220FFF773FD3A465146022000F022FFB9F10109EBD108F10108B8F1400FE2D12D4B38E04FF0010A4FF000080DF1200B02F086F844
:400680004FF0000959460120FFF7A8FD08EB090300270493049B1BF807203B44DBB29A4209D08DE80C0041463B464A461E48FFF702FE4FF0000A0137402FEBD109F101091B
:4006C000B9F5807FDED108F10108B8F1400FD5D151461648FFF7EFFDBAF1000F00F01A81134B1B8807A8ADF81C3094E249010000F900000091000000C50000008881FF1F0B
:400700000F3900000B390000123900002A3900003D390000ED81FF1FFE81FF1F47390000BC380000BE3800005639000072390000C0380000206FFFF74BFE94F8780001F081
:40074000F5FD94F8780001F0D9FD02F009FCB94BDFF8FC821A78002702F0FB021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F0F7FB0220FFF7DCFCF9
:40078000012141F6FF734FF48042084602F046FB84F8B60001F068FF08F807000137402FF8D1DFF8B0A200270AF195091FFA89F80137402F14BF3A4600221AF8010F2244C0
:4007C000062392F82420402101F082FF424646F240419AF8000001F08DFF08F14008402F1FFA88F8E4D196F8793053B196F87C30F36000233374237C002BFCD000233374EF
:40080000F36000234FF0FF32236062602372236894F8B600234493F8241001F0DDFE94F8B60001F09BFE012194F8B60001F06EFE2368002BFCD0002398467360D6F814A0D4
:40084000012701F0A3FF6369B4F87A20CAEB030393420DD367B1042195F8B60001F0C8FE94F8B60001F0D4FE0028F9D107463072237AFBB96A682B689A4202D1002FE0D1D9
:4008800018E00220FFF758FC6968402209EB8111022000F005FE6A68674B01321340002BBEBF03F1FF3363F03F03013308F101086360C6E70220277AFFF73EFC0022114687
:4008C000022000F0EDFD0220FFF736FCFFB2FFF7A5FC002001F012FD37B15848FFF7EBFC0220FFF70FFD06E0554B08A81B88ADF82030FFF7F5FC227C4146237A5148FFF7BB
:40090000DAFC15E25048FFF7D6FCD4F87A7017F03F0701D0032009E2286FFFF759FD95F8780001F003FD95F8780001F0E7FC012001F002FD02F014FB444BDFF814811A7857
:4009400042F004021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F003FB01214FF4804341F6FF72084601F0E9FC85F8B60001F077FE08F8070001378C
:40098000402FF8D1DFF8CC90002709F195031FFA83F804930137402F14BF3A46002219F8010F2244052392F82420402101F090FE414646F2475299F8000001F09BFE08F103
:4009C0004008402F1FFA88F8E4D100274FF0FF33376098467360BB463B46D6F87A9037725FEA99190CBF4FF0010A4FF0000A2168114A01310A40002ABCBF02F1FF3262F03B
:400A00003F026068B8BF013282426FD02BB1227A002A7AD12A7C002A77D12068049A059302EB8010BAF1000F16D040223F2102F0F7FA1CE0906400403F0000807C390000D7
:400A4000C238000096390000A939000097650040AC81FF1FAB81FF1F014601370120FFF7BDFBC7EB0903D3F1000A4AEB030A2168B34A01310A40002ABEBF02F1FF3262F0BF
:400A80003F02013222606268059B01322ED12A683F2A2BD14FF00008C5F8048001F080FC85F808806B6895F8B6002B4493F8241001F092FD95F8B60001F050FD012195F8BF
:400AC000B60001F023FD95F87E30EB6085F81080237C002BFCD04FF00008012086F8108001F06AFC404601F027FC00E023B1237A5BB92B7C4BB90123626842453FF477AFC1
:400B00000BF1010BD5F8048071E701F04FFC012001F012FC002001F04FFC042194F8B60001F066FD94F8B60001F072FD80460028F8D196F8B60001F0FFFC337C327A029318
:400B4000012303920193CDF800A05B463A4649467C48FFF7B0FBC6F80C80BAF1000F0BD0FFF75CFB002001F0C9FB237A63B17648FFF7A1FB0220D9E0B945F1D07349012035
:400B8000FFF72CFB0137F7E77148FFF794FB714B3DE094F8780001F0C9FB206FFFF718FC6D48FFF788FB94F87930E36000232374237C002BFCD0012001F0FEFB00233374CE
:400BC000237C002BFCD0002001F0F6FB00236348F360FFF770FB624B19E0002084F86A00FFF7F6FB5F4B12E094F8743023B195F875200AB985F8782094F875201AB113B9F6
:400C0000012385F878305848FFF79EFB574B1B88ADF8203008A8FFF763FB89E0FFF782FB02F07CF8002002F01FF82A2701F04AFF002001F0EDFE3A46002108A802F0F0F9E0
:400C400017238DF820308DF8217001F09FFD002001F048FB002002F0DBF8C82001F058FD0DF12200FFF7F2FA0DF13600FFF70FFB01F08CFD012002F0CBF8322001F048FD4D
:400C80000DF12600FFF7E2FA0DF13A00FFF7FFFA012001F027FB4FF4967001F039FD01F075FD0DF12E00FFF7D1FA0DF14200FFF7EEFA002001F016FB4FF4967001F028FD84
:400CC00001F064FD022002F0A3F8322001F020FD0DEB0700FFF7BAFA0DF13E00FFF7D7FA012001F0FFFA4FF4967001F011FD01F04DFD0DF13200FFF7A9FA0DF14600FFF756
:400D0000C6FA002001F0EEFA4FF4967001F000FD01F03CFD002002F07BF8002384F86A3001F07EFF01F050FE74E70120FFF7EAFA032000F07BFC0E48FFF7BDFAFFF7E4BBB6
:400D40003F000080B3390000E33900004092FF1FED390000C4380000F5390000033A0000C6380000C8380000FE81FF1FCA380000103A00002DE9F04172B6884B61221A70F9
:400D8000A3F5F06301221A801924854A9C7092E803008033062283F8002283E80300522203F580731A707F4B7F4A1B787F4EDBB2137040F618027E4B00251A8041F25122A6
:400DC00023F8022C33784FF4F07003F0010343EA450502F0BDF8013C05F003052ED0032DF0D1744B4FF480721A8007221A70724A002548211570917002221D705D7103F893
:400E0000032C0422DA716D4A6D4C13786D4E43F00103137012F8013C062743F0030302F8013C2378012243F0800323705B4B1A70654A137843F02003137000E0FEE707FBAD
:400E4000056300219A881868013502F0E9F8072DF5D15E485E4E002550F8041F05F1105303F1480221F0FF074933C9B20B4452005B0002329A4206D012F802EC12F801CC0C
:400E80000EF807C0F5E7B0420D44E5D1514A002313609360136193614F4B504F1A68504BDFF888811A604F4B1A684F4B1A604F4A137843F002031370137C43F002031374F7
:400EC0002378A2F5863243F040032370413A137843F010031370464A464B07CA03C31A80454A2833106843F8250C127903F8212C424A07CA03C31A80414AE83B07CA03C33B
:400F00001A80404A083307CA03C31A803E4A3F4BA2F5616203CBC2F8100EC2F8141E1378042043F008031370394B02F5AA521B783D78DBB298F80060EDB203F007010C329F
:400F40001B091170F6B2537045F003033B7046F0030388F800302F4B48221A702E4A402313702E49937013729372082382F81F3220220A7048710A72294A0A20137001F0C7
:400F8000DDFB284B88F8006044223D70264D1A7094E80F0007C52B80BDE8F081004800404C0A00480F010049A146004025420040224200400440004006400040A2430040BE
:400FC000A0430040153A0000E8460040FCFFFF478C00004800760040540A0048F846004020760040580A004828760040035001400C0A0048C0510040180A0048200A0048A5
:401000002C0A0048380A004832510040440A0048CF0100491D51004001590040235B0040585B004076580040B0430040F946004008B501F0C9FF03680C2B00D1FEE7FEE7CA
:40104000084908B50B68084A1844821A802A01DC086005E001F0B8FF0C2303604FF0FF33184608BDCC80FF1F9093FF1F80B51148114B0025C0B1A3F1100192C92246043933
:40108000161BB74204D051F8046F42F8046BF7E7114653F8046C8C1AA64202D041F8045BF9E701381033E5E701F094FFFFF7DCF9FEE700BF01000000E43B0000124A134BF0
:4010C00010B51A60124A134C1368134843F4007313600023032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF73BFEBDE8CA
:40110000104001F0EDB900BF0004FA050CED00E014ED00E0000000000080FF1F31100000BC760040C080FF1F08ED00E0F8B501F017FF4B4A01271378022643F001031370EA
:40114000137C484C43F001031374474B02F5E3521F700B3203F8946C1378054603F07F031370002001F0EAFA2378404A03F0F90323701378384603F0DF03137023783B4325
:40118000237001F0DBFA282001F0D8FA384B30461A7802F07F021A701A7802F0BF021A7023783343237001F0C9FA2378314A43F0040323700023137053702F4AFF2199544A
:4011C0000133092BFBD1284601F0CEFE0721172001F0FCFA2949172001F0EAFA0721182001F0F4FA2649182001F0E2FA0721152001F0ECFA2349152001F0DAFA0721052032
:4012000001F0E4FA2049052001F0D2FA0721062001F0DCFA1D49062001F0CAFA0721084601F0D4FA1A49072001F0C2FA0721082001F0CCFA1749082001F0BAFA0021162047
:4012400001F0C4FA1449162001F0B2FA07210C2001F0BCFABDE8F84010490C2001F0A8BAA5430040944300409D60004012600040F851004084600040B592FF1FFB1A00008A
:4012800035190000F91A00002D1A0000591A0000891A0000C11A0000011B0000751B0000214B224A10B5187000231370204A40201370204A0F2413701F4A13701F4A1370D9
:4012C0001F4A13701F4A13701F4B4FF400021A604FF080721A604FF400121A6020221A601860802018604FF480701860174804704FF480001860164B1A70933B19B91A7851
:4013000002F0FE0202E01A7842F001021A70114B03221A70802203F8202C012001F018FE0D4B04221A7010BDD092FF1FD692FF1FD492FF1FD592FF1FD192FF1FC092FF1F97
:40134000D392FF1F4893FF1F00E100E09E6000409C600040286000401260004070B5074C054623780E461BB9FFF7E0FE0123237031462846BDE87040FFF792BF8092FF1F7A
:401380000A4A002313700A4A13700A4A13700A4A13700A4A13700A4A13700A4A13700A4B03221A70802203F8202C7047D692FF1FD492FF1FD592FF1FD192FF1FC092FF1F05
:4013C000D392FF1F4893FF1F28600040014B1878704700BFD592FF1F044B1A7802F0FF001AB118780022C0B21A707047D492FF1F024A0C2303FB002040787047DC92FF1FB8
:40140000431E072B0CD8074A064B00010344805C5B7800F00F0043EA0020023880B2704700207047FC5F00401A4A38B50C2303FB00231B79090C13F0800F00F1FF35044670
:4014400019BF8AB24FF480438BB24FF48042032D18D8DFE805F002070C110021084601F01BF80DE00021084600F0FAFF08E00021084600F0D9FF03E00021084600F0B8FF3E
:40148000054B1855EDB2072D03D801F0EDF8034B185538BDDC92FF1FAC92FF1FB592FF1F431E072B2DE9F0470446894615465CD82F4F0C2202FB0072D388DFF8B8A09BB274
:4014C000C3F500739D424FF00C0303FB007388BFD588DB7884BFC5F50075ADB2254A43EA15230601B354B244EBB28AF80130224B1A5C9846FF2A01D1FFF796FF0C2303FBBF
:40150000047200215170B9F1000F28D03DB31B4F385D01F011F811232946FE2218F8040001F0D6F806F5C04278321FFA89F118F8040001F0DFF8124D18F80410385D01F004
:401540004BF80121385D00F0E1FF735D43F002037355735D03F0FD037355BDE8F08703FB04746379DBB28AF80230BDE8F08700BFDC92FF1FFC5F0040B592FF1FAC92FF1FD4
:40158000706000402DE9F047044615468846002940D0431E072B3FD8FFF732FFA84203D22046FFF72DFF05461D4E335DFF2B03D141462046FFF738FFDFF868A027011AF893
:4015C000040000F0B9FF1223FE222946305D01F07FF807F5C0411FFA88F27831305D01F089F8DFF84490315D1AF8040000F0F4FF01211AF8040000F089FF17F8093043F0F1
:40160000020307F8093017F8093003F0FD0307F8093002E00D4600E000252846BDE8F087B592FF1FAC92FF1F70600040431E072B0AD8064A0C2303FB002300225A705A7991
:40164000034BD2B200011A54704700BFDC92FF1FFE5F0040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB21380194A00231488E7
:40168000D8B2A4B27CB1082B0CD050680078C0B2E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F080032B700F23237022
:4016C000022301E0022323701370094B1870087030BD00BF4C93FF1F4893FF1F00600040C492FF1FC192FF1FD692FF1FD292FF1F4993FF1F074B02221A70074B80221A70AE
:40170000064B0F221A70064A00231370054A012013707047D692FF1FD292FF1FC192FF1F4893FF1F4993FF1F30B5164B16491B780A8803F00F03023BDBB21A4492B20A80CC
:40174000124C134A0020118889B279B173B15568215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370094A137883F080031370084B0B221A70DF
:4017800030BD00BF296000404C93FF1F00600040C492FF1F4993FF1FD292FF1FC192FF1F064A06231370064A01201370054B80221A70054B00221A70704700BFD692FF1F52
:4017C000C192FF1FD292FF1F4993FF1F054B9A683AB19A68044910709A680988518000229A607047C492FF1F4C93FF1F08B5124B1A78D2B21A701B78DBB21A0602D50F4A1E
:40180000137008BD0220FFF7E1FF0D4B1B7803F06003202B05D0402B06D043B900F012FC04E001F0A5FB01E000F046FD10B9034B03221A7008BD00BF28600040C192FF1FC0
:401840000060004008B5084A084B0120197813880B449BB21380064B00221A70FFF7B6FF044B03221A7008BD4C93FF1F4893FF1FD692FF1FC192FF1F08B50C4B1B78DBB25E
:40188000042B07D0062B09D0022B0DD1BDE80840FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BFD692FF1FC192FF1F08B5054B002201201A70FFF7B6
:4018C00085FF034B03221A7008BD00BFD692FF1FC192FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B002201201A70FFF76BFF054B03221A7008BD00BFA5
:40190000C092FF1F08600040D692FF1FC192FF1F074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF7047D692FF1F38B51D4C2378DBB2DD0634D51B
:4019400018060AD503F00F03012B2ED1FFF74EFF174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B1B7813430F4A13705F
:401980001278934211D10A4A0849154613782078DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD28600040C192FF1FD292FF1F4993FF1F29600040AD
:4019C000054A00231380054A916819B191680B7092685380704700BF4C93FF1FC492FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4B00221A70FFF7E0FFAC
:401A0000094AD1799379028843EA012392B2934238BF0380FFF728FE012008BDC492FF1FD692FF1FD292FF1F00600040084B01221A700F3B9B7C074B1A7B02F00302012A07
:401A40001EBFDA7B82F08002DA7301225A7370470B600040DC92FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7601225A76704700BFFE
:401A80000B600040DC92FF1F0B4B04221A700F3B93F83230094B93F8242002F00302012A1EBF93F8272082F0800283F82720012283F82520704700BF0B600040DC92FF1F78
:401AC0000B4B08221A700F3B93F84230094B93F8302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BF0B600040DC92FF1F7047FFF741BC000081
:401B0000F0B5184B184E19780C27C9B201234FF0000C31B3CA0720D5144A4FEA031E7244947850782040C5070DD507FB03652C79240608D5147804F0FE0414706D790C4C35
:401B4000EDB204F80E50840706D507FB036425792D0658BF84F801C090700133DBB24908D7E7F0BD9F600040DC92FF1F70600040FE5F004000F0ACBC70B50446184B88B021
:401B800003AA03F11006154618685968083303C5B3422A46F7D11B782B70FCB12223237001AD03232846637000F08AFE002220461146AB5C08AC04EB131414F8144C03F053
:401BC0000F03847008AC234413F8143C0132082AC1700371417100F10400EAD108B070BD3F3A00002DE9F0431C4D01222E460C201F274FF0800E4FF0080C194B00FB02580B
:401C00001401234418705F70164998F805902144B9F1000F07D098F8044024064CBF887081F802C001E081F802E000FB0261CC880132E4B29C71CC88092AC4F30724DC71A2
:401C4000CC88E4B21C71C988C1F307215971D4D1054BFF221A70BDE8F08300BFDC92FF1F70600040FC5F00400A600040064B074A1B7802EBC30253681A7C824286BF03EB6F
:401C8000C003586900207047D092FF1FA03A00002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF800C1E4B203EBC0000C260027FE
:401CC0004FF0010E834268D01A78A24263D11CF80420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B009F0030981F804B093F803B005F80AB0A6
:401D0000B3F804A0A1F808A093F902A0BAF1000F0BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF4FF005094FF0090981F805904F704FEAA3
:401D400002191A4906FB0282494481F802E0B2F808A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F806A0B2F80690C9F3072981F8FE
:401D80000790B2F806905FFA89F981F80490D288C2F307224A71083394E7BDE8F88F00BFD592FF1FDC92FF1FD192FF1FFC5F004070600040C292FF1F08B5064B187801384A
:401DC000C0B2FFF753FF20B143681B7900EBC300406908BDD592FF1F00212DE9F84F0B464E4E0C2707FB01F401313219092933554FF000059370494CD37013819372537031
:401E00005371EFD118B1464B1D70464B1D70464B1A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4B4FF0000C1A7814BF42F0010273
:401E400002F0FE021A70027AD20007FB0541C36803EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B01E7893F801B01EF80660B34576
:401E80001AD181F804A0DE780E7093F902A0DE78BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052609264E7181F801C00833CBE70135092D89
:401EC000C3D1C1680A328B1C0A440C200833934209D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B0121186000230C2000FB0142D38012890131134463
:401F00009BB203F00102134409299BB2F2D1BDE8F84FFFF767BEBDE8F88F00BFDC92FF1FC292FF1F4A93FF1FD592FF1FD392FF1FD892FF1F114B1B7903F07F035A1E072A3C
:401F400019D80F490C2202FB031291781B0141F0010191700021D170517841F002015170127912F0800F074A1A4414BF8D2389239370FFF715BC0020704700BF0060004065
:401F8000DC92FF1FFC5F004030B4194B1A7902F07F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D97029461201505D114400F07F0050555A7802F013
:401FC000FD025A701A795B78120605D5012B01D18C7006E00D2303E0012B0CBF082309238B7030BCFFF7DCBB002030BC704700BF00600040DC92FF1FFC5F004010B50D4BA5
:402000000D4C21791878C9B20138C0B2FFF72EFE43681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD002010BDD592FF1F00600040C292FF1FB6
:402040004A93FF1F38B58A4A8A4C13780021DBB221801806517840F18D800A2900F20581DFE811F05D00030103010301030103010B0003017E0003018200D3787C49012B9C
:4020800009D17D4B1A787D4B03EBC2035B685B686360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7863689B7843EA02232380BDE83840FFF7EE
:4020C0008FBCCB78032B26D16D4B00228878D5B2854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D018780344EAE764499278097C914203D180
:402100006248FFF739FD614B1A78002A00F0AD801A78228018E0BDE8384000F029BF13F0030313D0022B40F0A0802380504B0C211B7903F07F02564B01FB02339A78554BC3
:40214000D2B21A7000225A706360B6E702222280514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4A1344E9E701390A2977D8DFE801F0377608
:402180004F76067676760A7620009378454ADBB25AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E0481EC0B2FFF75AFD0028EED155E0FFF793
:4021C0001DFF002851D02A4A384913791279DBB2D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303012B2BD009D3022B37D11D4B9B78002B47
:4022000033D1BDE83840FFF7BFBE194B9B78012B2BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9BDE83840FFF77EBE0D4B9B78012B14D1B7
:40224000154A137843F0020313700AE0084B1A795AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF79BBA002038BD00BF00600040C492FF1FD092FF1FA03A000049
:40228000043B00008C3A0000773B00006893FF1FDC92FF1F8192FF1FD392FF1FD592FF1FC292FF1FC092FF1FD492FF1FD192FF1F4A93FF1FD792FF1F074B1A78120609D546
:4022C0005B78012B06D1054B054A5A6012781A80FFF786BB0020704700600040C492FF1F643A0000014B1870704700BF76650040014B1878704700BF67640040014B187035
:40230000704700BF77640040064A0123136002F688321268E0211064034A1170A2F540721360704780E100E000E400E0014B1870704700BF74640040014B1870704700BF92
:402340007565004073B515461E460B4C05230022019200920A4601461846237000F064F932462946207800F01FF90221207800F009F9207802B070BDD080FF1F064A042331
:40238000136002F688321268E0219064034A1170A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04221A60704780E100E0014B1870704700BF30
:4023C00074650040704738B505460078012428B100F066FD285D0134E4B2F8E738BD08B50D2000F05DFDBDE808400A2000F058BDF7B516461F460B4C002303250193009362
:402400000A4601462846257000F00EF93A463146207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1FF7B516461F460B4C00230225019300930A4601462846257030
:4024400000F0F2F83A463146207800F0ADF82946207800F097F8207803B0F0BDE180FF1FF7B516461F460B4C00230125019300930A4601462846257000F0D6F83A463146DE
:40248000207800F091F80221207800F07BF8207803B0F0BDE280FF1F73B515461E460B4C0023019300930A4601461846237000F0BBF832462946207800F076F8022120782A
:4024C00000F060F8207802B070BD00BFE380FF1F024B1878C0F38010704700BF8F450040074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFCC
:40250000E480FF1FF87B00400078004017280FD8084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001EA
:40254000C25C02F0FE02C254C25C02F0DF02C25400207047012070471070004017280DD8074900010B4603441A7942F004021A71435C43F001034354002070470120704740
:402580001070004017280BD8064A0001835C490003F0F10301F00E011943815400207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBF85
:4025C000C00000F1804000F5EC4081809ABFC280002001207047000017289FBF034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBFDC
:402600001143195400200120704700BF1470004017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC4422
:40264000D2B222709DF8082003F00F0343EA0213DBB263709DF80C30002003F00F03A370E07010BD012010BD10B500F079FC0A4A5378182B0AD91478013B5370E30003F1FB
:40268000804303F5F0431B78137000E0FF2400F06BFC204610BD00BFE480FF1F030610B5044611D400F05CFC084AE300117803F1804303F5F0431970537814700133537094
:4026C000BDE8104000F050BC10BD00BFE480FF1F30B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5D2
:40270000F04081805ABFC280002001207047000038B50446084DB4F5004F05D9286800F017FCA4F50044F6E7034B58686043BDE8384000F00DBC00BFEC80FF1F024B1B7AB4
:40274000584300F005BC00BFEC80FF1F0E4B00F003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F060
:4027800010021A70704700BF83430040014B01221A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230009
:4027C00042F82310704700BF08ED00E000F01F0000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040334
:4028000013600A4B4FF47A72DB68B3FBF2F3084A1360084B4FF400421C60C3F8E82010BD8492FF1F8D28000010E000E0EC80FF1F14E000E018E000E0024A136843F0020334
:402840001360704710E000E008B5FFF7F5FF034A136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BF8492FF1F024B186891
:40288000C0F30040704700BF10E000E038B5FFF7F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BF8892FF1F024B03EB80035868596070478492FF1F1F
:4028C000134B144A1B78DBB20360127843EA0223114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA024382
:402900000A4A4360127843EA02634360704700BF0301004904010049EC460040020100490101004900010049050100490601004910B500F015FB204A044613780A2043F07D
:4029400002031370137C43F00203137412F80A3C43F0010302F80A3C937943F00103937102F5AB52137843F003031370134B18221A7013F8012C42F0400203F8012C13F837
:40298000012C02F0FC0203F8012CCE2203F8062CA3F597530222183B1A70094A137843F008031370FFF7CAFE064B10222046BDE810401A6000F0D8BAAB4300400E59004026
:4029C0002F5B004080E200E008B500F0C9FA0F4A137803F0FE031370A2F5AA521D3A137803F0FD031370137C03F0FD03137412F80A3C03F0FE0302F80A3C937903F0FE0388
:402A00009371BDE8084000F0AFBA00BF08590040044A137803F03F0343EA8010C0B21070704700BF08590040082804D00A280CBF8223C22300E0422308380E4AC0B2042812
:402A4000137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470A590040503A00005293FF1FB7
:402A80005493FF1F5893FF1F08B5102000F0A6F907210420FFF79AFE07490420FFF788FE064A0C20137843F006031370FFF7BCFF034B00221A8008BD812B0000095900402E
:402AC0005093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF72ABFA092FF1F044B1A7802F0FB021A701A7842F001021A7070470859004010B5084B1C7814F0F1
:402B0000010403D10028F9D0002404E02046FFF715FE024B1B78204610BD00BF09590040034A044B1B881088181A00B2704700BF5893FF1FA25B00400E4A13881BB223B1D5
:402B400011880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270475293FF1F5493FF1F5093FF1F29
:402B80007047000010B500F0EBF9214A044613780A2043F001031370137C43F00103137412F80A3C43F0020302F80A3C937943F00203937102F5AA521832137843F0030343
:402BC0001370144B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222123B1A70094A137843F008031370FFF79FFD074BEE
:402C000008222046BDE810401A6000F0ADB900BFAB43004006590040275B004080E200E008B500F09DF90F4A137803F0FE031370A2F5AA52153A137803F0FE031370137C9E
:402C400003F0FE03137412F80A3C03F0FD0302F80A3C937903F0FD039371BDE8084000F083B900BF00590040044A137803F03F0343EA8010C0B21070704700BF0059004016
:402C8000082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBDD
:402CC000F1F305490B60054B1A807047025900405A3A00005E93FF1F6493FF1F5C93FF1F08B5102000F084F807210320FFF76EFD07490320FFF75CFD064A0C20137843F035
:402D000006031370FFF7BCFF034B00221A8008BDD92D0000015900406093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF728BFA192FF1F044B1A7802F0FB02D6
:402D40001A701A7842F001021A7070470059004010B5084B1C7814F0010403D10028F9D0002404E02046FFF7E9FC024B1B78204610BD00BF01590040034A044B1B88108822
:402D8000181A00B2704700BF5C93FF1FA05B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF86
:402DC0005B42134493FBF1F000B270475E93FF1F6493FF1F6093FF1F70470000034A00F0F800137803431370704700BF02410040034A00F0F800137803431370704700BF9A
:402E000006410040014B1870704700BF72640040014B1870704700BF7864004073B515461E460B4C04230022019200920A46014618462370FFF7F8FB324629462078FFF7B3
:402E4000B3FB02212078FFF79DFB207802B070BDFC80FF1F074A0223136002F688321268E0215064044A11706FF440710A441360704700BF80E100E001E400E0014B18708C
:402E8000704700BF75640040014B1870704700BF76640040014B1870704700BF79640040FEB5494652465B460EB40746244909688A46244A12682448022100F071F80300AD
:402EC00020480068C018204900F06AF8143883460121C9430C460125002600F041F8814651460B7823400B705846013000F030F83800F04028400B78234003430B705846AA
:402F000000F026F80136072EF2D9002001300138013001200B78234003430B705846043000F016F8484600F01FF800BF00BF00BF0EBC894692469B46FEBD00BFAFF3008039
:402F4000D480FF1FF880FF1F00C20100000000000230800803D000BF01380046FCD17047EFF3108072B6704780F31088704700BF094A137803F00303012B0AD0022B09D181
:402F800013790C2103F07F02044B01FB02339B7A00E013790020704700600040DC92FF1F002902D0B0FBF1F0704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB0B
:402FC00011217047704700BF014B1868704700BF6081FF1F0E4B70B51E460E4C0025E41AA410A54204D056F8253098470135F8E700F0DEFD084B094C1E46E41AA41000251E
:40300000A54204D056F8253098470135F8E770BDBC3B0000BC3B0000BC3B0000C43B000003460244934202D003F8011BFAE7704730B5141E05469BB0184604DA8B232B6026
:403040004FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029305934FF6FF7300910491ADF80E3002461E9B6946284600F073F8431CBCBF8B232B6014B1009B0022F6
:403080001A701BB030BD000007B5009313460A46014603480068FFF7CBFF03B05DF804FB6081FF1F2DE9F0478E6882469E420C46914698463ED88A8912F4906F3AD025685F
:4030C000096902236F1A656905EB450595FBF3F57B1C43449D4238BF1D4653050FD5294600F04AFB064698B13A46216900F0D2FAA38923F4906343F08003A38113E02A462B
:4031000000F098FB064670B92169504600F0E8FA0C23CAF80030A3894FF0FF3043F04003A381BDE8F08726613E44266046466561ED1BA560464528BF4646494632462068B9
:4031400000F0B3FAA36800209B1BA36023681E442660BDE8F08700002DE9F04F9DB003938B8980461C060D4616460DD50B695BB9402100F001FB2860286118B90C23C8F8D4
:403180000030CDE040236B610023099320238DF82930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BF9D02746F3E74B46324629464046FFF7EA
:4031C00071FF013000F0A780099B4B4409933B78002B00F0A08000234FF0FF3204930793059206938DF853301A930126052221784E4800F041FA671C049B38B14B4A3C46E7
:40320000801A06FA00F018430490EFE7D90644BF20228DF853201A0744BF2B228DF8532022782A2A03D0079A00210A200BE0039A111D12680391002A10DA524243F002006C
:40324000079204900BE027463B780134303B092B03D800FB02320121F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E010
:40328000002319460593781C0A2407463A780130303A092A03D804FB01210123F5E703B1059103223978224800F0E6F940B14023CBEB000003FA00F0049B01371843049053
:4032C000397806221B487E1C8DF8281000F0D4F988B1194B33B9039B073323F007030833039314E003AB00932A46144B04A94046AFF3008007E003AB00932A460F4B04A937
:40330000404600F093F8B0F1FF3F824603D0099B5344099342E7AB895B0601D4099801E04FF0FF301DB0BDE8F08F00BF8B3B0000913B0000953B000000000000A5300000D1
:403340002DE9F04791461F460A698B6806469342B8BF1346C9F8003091F843200C46DDF8208012B10133C9F800302368990642BFD9F800300233C9F80030256815F00605F2
:4033800010D104F1190A07E00123524639463046C04701301AD00135E368D9F800209B1A9D42F1DB94F843302268003318BF012392060FD5E118302081F843005A1C94F84E
:4033C00045102244023382F8431003E04FF0FF30BDE8F08704F1430239463046C0470130F4D02268D9F80050E36802F00602042A08BF5D1B2269A3680CBF25EAE57500252C
:403400009342C4BF9B1AED184FF000091A344D4509D00123224639463046C0470130D5D009F10109F3E70020BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9BE3
:4034400001F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A40F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B880A0
:403480000A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F14205111D1960136884F84230A8E021681A6811F0800F02D0111D196008E011F0400F02F104011960E2
:4034C00002D0B2F9003000E01368002B3CDA2D225B4284F8432037E021681A6811F0800F02D0111D196007E011F0400F02F10401196001D0138800E01368227E5C496F2A40
:4035000014BF0A2208221BE078225A4984F845202268186812F0800F00F104051D6003D1550601D5038800E00368D00744BF42F0200222601BB9226822F020022260102266
:40354000002084F8430001E049490A226568002DA56008DB206820F0040020602BB9002D7DD175460CE0002B79D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D131
:40358000082A0BD12368DA0708D5236962689A42DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A6810F0800F496903D0101D1860136808E010F0400F02F1040087
:4035C0001860136801D0198000E0196000232361754616E01A68111D1960156800216268284600F049F808B1401B6060636804E004F1420584F8422001232361002384F8A9
:403600004330CDF800803B4603AA21463046FFF797FE013002D14FF0FF3026E023692A4639463046C0470130F5D023689B0710D5002504F1190907E001234A4639463046F8
:40364000C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842B8BF184605E00B7804F1420584F842308AE705B0BDE8F0833F3A00009C3B000010B5C9B202449042CF
:40368000034605D01C7801308C42F8D1184610BD002010BD10B5431E0A44914204D011F8014B03F8014FF8E710BD884210B501EB020301D8421E0BE09842FBD28118D21A41
:4036C000D34204D013F8014D01F8014DF8E710BD994204D011F8014B02F8014FF8E710BD38B50546002944D051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B912
:403700006360146030E0A3420DD92268A018834201BF18685B681218226063600C6023E0A24203D813465A68002AF9D118681918A1420BD12168014458188242196013D1F2
:4037400010685268014419605A600DE002D90C232B6009E021686018824201BF106852680918216062605C602846BDE8384000F098B838BDA892FF1F70B5CD1C25F003051A
:4037800008350C2D38BF0C25002D064601DBA94202D90C23336046E000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B6896
:4037C0001360636018BF0C4615E00C464968E9E7174C23681BB9304600F052F820602946304600F04DF8431C18D0C41C24F00304A0420DD12560304600F053F804F10B005E
:40380000231D20F00700C31A0ED05A42E25070BD211A304600F034F80130EBD10C233360304600F03EF8002070BD00BFA892FF1FA492FF1FF8B5074615460E4621B91146D1
:40384000BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F885420ED929463846FFF78BFF044650B131462A46FFF713FF31463846FFF735FF01E03046F8BD2046F8BD40
:4038800038B5064C0023054608462360FDF7D8FB431C02D1236803B12B6038BD8C93FF1F7047704751F8040C0028BEBF091851F8043CC018043870470000000005020902A2
:4038C0000B020D020F021102130215027265706C792030782530327800686F6D696E6700626567696E6E696E67207365656B2066726F6D20256420746F2025640066696E08
:403900006973686564207365656B00796573006E6F00647269766520303A20257320647269766520313A2025730057616974696E6720666F72205553422E2E2E00555342F3
:4039400020726561647900636F6D6D616E6420307825303278006661696C2025642B25642B2564203D3D2025642C206E6F74202564007061737365643D256400756E646544
:403980007272756E206166746572202564207061636B65747300636F756E743D256420693D256420643D256400636D645F777269746500703D25642063723D256420637729
:4039C0003D256420663D256420773D256420696E6465783D256420756E64657272756E3D256400756E64657272756E21007375636365737300737461727420657261736912
:403A00006E670073746F702065726173696E670069646C650000510040100040510040300000000140001000140140000800400140000A004C0140000200500140200030F9
:403A400031323334353637383941424344454600000100000004000000100001000000040000001028000000000104000100000000000000000157494E5553420000303043
:403A800030303100000000000000000012034D005300460054003100300030000100000001000000A83A000001000000773B0000000000000000000001000000C03A000003
:403AC00001000000493B000004000000E23A0000000000000000000000000000E03A0000FF00000001024000FF00000082024000FF00000003034000FF00000084034000F7
:403B0000FF00020304030904160346006C007500780045006E00670069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F006C006F0003
:403B400067006900650073000009022E0001010080320904000004FF00000107050102400000070582024000000705030340000A0705840340000A12010002FF0001080921
:403B800012006E0100020180014300232D302B2000686C4C00656667454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E4670475900000094
:403BC000BD100000F8B500BFF8BC08BC9E46704735000000E83B0000C880FF1FA00000002812000000000000000000009093FF1FFF000000675000400C0000000700000097
:403C0000FFFFFFFF7F8000003F0000000000007D00FA0000400000000090D003FF000000000000000000000000000000000000000000000000000000000000000000000031
:403C4000893B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080
:403C80000081FF1F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065
:403CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C4
:403D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083
:403D40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043
:403D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
:403DC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C3
:403E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082
:403E40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042
:403E80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002
:403EC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C2
@@ -4098,68 +4098,68 @@
:40FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041
:40FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
:0200000480007A
:400000000145004008520040015B004001650040010101404D0201403D0301404C0401404D0501404D060140500701404B0801404B0901404B0A0140500B0140470C0140CB
:40004000500D0140520E0140350F014046140140541501404B160140561701404718014044190140591A0140571B01400A400140104101400E4201400943014004440140BE
:400080000D4501400A4601400F470140094801400F4901401B4C0140084D014008500140045101407E0208440905108011821801600C610A7C4027212A0A8C8000010109B1
:4000C0000202040805090808090F0B100C080D010F02100F1120140416011709180819101B0E1D011E01210422082301240829092A0E2C0D320F331F35203B083E043F1020
:400100005608580459045B045C905D905F01850287018C01900F9401960898249A089E07A008A101A222A302AA08AE10B01FB101B302B420B90ABE10BF05C202C70EC810AC
:40014000C9FFCAFFCBFFCF83D804D904DA04DB04DC09DD09DF01030204A10620074008010A060B200C800D100E400F2010421110150416821720180419011E10202021010F
:40018000262027202A012C042E023508376138083E583F0240045208588859215A025D4060026108621265806F0180068140874088408A088E209880C0F1C2FFC4FBCAA1EC
:4001C000CCF0CEF2D004D61FD81FE20CE6C5EE82010D04020601070109080C010D080E0E100F130E150F161019081C201D082101220F2302240125042604270128012908CA
:400200002A082C012F08301F3220330F3E043F045608580459045B045C095D905F01810182088302840885028A108B018C088D038F049102920194049701982099029A1FB5
:400240009C089D02A202A302A408A501A704A808A902AC1FAD03AE20B107B43FBF01D804D904DB04DC09DF0100400108048006A0070809880A400C810E080F20100511082C
:40028000130115251740185019011B011E081F20210827402AA02B902C052D022F20308031213208350136803728388039243B013D083E4A3F2158405C105D806180851076
:4002C00087029102938094A195349644972099809B209C0C9D089EBAA480A602A713A908AC03B010B520B601C0F5C2FDC4FFCAFFCCFFCEFFD638D808E20AE648E880EA03A0
:40030000EE820003010D050506010801090C0B020C010D0D1001111012021602170D1801190D1C011D0D2201230D2401250D280129092C012D012E022F02310C3510360355
:4003400037033E403F51580459045B045F0180208102820F8404860A882F89028D028EA09204948095039640970C98049A099E10A020A102A20FA480A802AC01AD0AAF0550
:40038000B060B108B21FB306B480B501B61FBE10BF01D804D904DB04DC99DF01000902080302048A0708082209880C800D100F9011501305158016A01710180919041A08AD
:4003C0001BD21D80210923042440254026102B422C042D012E402F20310836843721380239803A103D203E083F825D015F0169506AA06F0178017B807D027F8080048604BE
:4004000089108A028F01938094A19525964497219B209C0D9D0A9EA89F08A321A480A520A68AA790AD01B040B210C0FFC2FFC4FFCAF9CCF2CEFDE242E401EA01000103027E
:4004400004E0050108010A080B020CE00F02100F1280130814481602170218201B021E071F02200422482302261027022A082B042F10311F34E0361F382039023F015804DF
:4004800059045B045C095F0180038109840387318A018B098C038F06900391129309940395099712980399409E02A003A309A603A709A803A909AC03AD49AF24B338B40349
:4004C000B540B707BB88BE10D804D904DB04DC90DF010080012002800320048A052008180A010B400C020D080E0610021325172918081E061F802002215423252480284155
:4005000029202B202C872D202F203108321233013448350137A0380239883B103C803E043F115A806E408340860287048A0690029289935094019704981A99019B889C84CD
:400540009D209F20A0C2A108A280A328A401AB10B204C0FFC2FFC47FCAFFCCF7CEFFD608E080E620EA85EE2002800404050D064808200A400C0111011210144816021A07E2
:400580001B051C401E202608280129102A082C0F2D0A3020310C32C03303341F362037103A083E413F4056085804590B5B045C995D905F01822083018607870F88218A0825
:4005C0008B018C218F019210930E9428964297059AC89B039F01A02FA280A301A444A628A709A90FAA20AD0FB105B21FB4E0B503B709BA20BF51D804D904DC09DF010001EA
:400600000184030805A4078009090A060D080E881006121015141701180219811A051B481D041E081F20210422412501264027082B052C822F2432113408350137A03908B7
:400640003C823D043F144410450858805B10630A64086610780284018601911092289358950896019704980A9B819D249F20A0C2A108A280A401A761A840AF11B040B504F1
:40068000B702C0FFC27FC477CAFCCCF5CEF2D60CD80CDE01E202E640E880EA10EE4002080349077F08010A280B090C2F0F091001117F1408160217091A071B091E401F2962
:4006C000221023722709280429782A282B042F19310732603348341F352837183F55580459045B045C095F01802081048440850186A088418A088C4F8E808F04920794041B
:40070000966898689A029B019C41A208A610AA40AD02B01FB304B503B6E0BA80BF04D608D804D904DB04DC99DD90DF010128024003010521070109040A810B080D080E0633
:400740000F80128013181608170218821A801D081E041F14221423102601271A2B012D042E012F253210341036843721380239083A403C023D1A3E0A3F54584060026240FE
:4007800068026B016F0A831886408B048C018D089342951496019714980899019B809C109D209E0A9F21A0C0A284A402A509A74AB308B504C0DFC2FFC45ECAF8CCF4CEFBE6
:4007C000D608D808E010E280E644EE820002012F020103800402060107070A060B200C020E010FC81002120114071528174218021A011B101C021E012121220523082544DD
:400800002607272829212A012C0731E03207331F3B023E04580459045C905F0182698502861988198E198F119019924493049419962298229A199B089C19A20EA306A61923
:40084000A702A910AA19AB01AD01AE19AF10B070B208B301B407B510B607B70EB928BAA2BB80BE04BF14D804D904DB04DC99DF010082012402400521060207200810094941
:400880000B200C020D090E010F04104213141514164017801A201C821D011E281F012010210423C025442680270829202A082B402C802F1A30803108329034483614378162
:4008C000390A3B503D403F046D408C10C0FFC2FFC4FFCAF7CCA6CE5FE210010E04080508060409080C0D0E020F08110812091504180819081A021D081E04200423012702A7
:4009000029082D08300C320C330F34033A0A3F045608580459045B045C095D905F01801382048402871088028B1F8C088E018F1F901991019202951F96099A089B049C0273
:400940009D1FA001A20CA308A602A720A802AB02AC1BAD1FB210B40FB73FBB80BE14D804D904DC90DF010108021104020540060807200A040B810D110F2211021405161004
:400980001702190A1A041E201F20210425402680270229442A212C802E202F2130803120320433113545371039163A803B033D843F2058806002680D6A508101821084A1C0
:4009C000880289028B048E5090029134922893859508980599459AA99B219C229D0AA080A121A311A40CA690AA88AD80AF10B111B504B648C0F5C2FBC4F8CAFFCCFFCE7FAE
:400A0000D608D808E248E401E602E809EE030001062008010A7E0D010E08107F167F1A041E1020022101247E26012A402C7F3501367F3B303E40580459045B045C905F0179
:400A4000804484118708881189078C078E088F109211941195A5974298119B429C119F21A011A307A433A5C6A644A721A878AA02AC20AD84AE02B3E0B51FB67FB71FB9A0BC
:400A8000BE40C004C5E0C6C0C80AC9FFCAFFCBFFD004D601D804D904DA04DB04DC90DD09DF01E2C001160201030204020540071409A80B400C810D200F2010041141130440
:400AC00015A016A019801F80214023152510270428222B402F8030083250384039083B103D8041014B025210688069756B116C016E406F02705071E972A07348810A8204C4
:400B00008404850487048A108C509040910292A8938094A295A496409733980199049B209C269D0A9EB89F18A141A351A484A530A68CA808B210B540C0FFC2FFC4FFCA8B79
:400B4000CC0ECE1ED001E003E208E402EA40EE060601083109100D0C0E080F021040130116021702180319011A101E0420382304240325082608290A2B042C022E2130400E
:400B8000310F3207351036383A803E013F10580459045B045C995F018001830C8401870188018A028B078C018F019001930194019701980199079E019F01A001A108A302BA
:400BC000A601A701A801AB01AC01AE02AF01B507B603B708BE40BF50D804D904DF0100820201032A05480608081909800B400D080E461002128013241501174818011D4E2B
:400C00001E01218022102408260228082BA22C082E022F103011328436063710380239A83D103F806D5080048280850186058C208D01900291A89248934494019620981A26
:400C40009A029B609C809D20A043A284A328AB80B604C0EFC2FFC4BFCAEFCCEFCE3FE080E451E8C0EE02000801010201050108040B010C010D010E081101130217011901F5
:400C80001A011D01210123022401250129012A022D01300332043303340836083A023E543F0440434502480149FF4AFF4BFF4D204EF05110580459045A045C095D095F017F
:400CC0006108624063406480664067408004840885CC86018722881F8C048D01900493119401961E9722980499F19C019E10A004A344A588A604A824A9AAAA19AB44AC0134
:400D0000AE22B020B30FB50EB61FB7F0BE41BF10D804D90BDC90DF01002001020301058907080B040C200D090E011010120816801764181019221A0A1B801D021E0222083E
:400D400025602711280929022B202C082E022F10301232843606371039A83A013D884010410248107C0283408520881089088B308C088D448F4091EA920193049602972033
:400D8000981B99819A839B0C9D209F10A022A108A286A320A408A601A7C0A904AB04AD01AE01B080B18AB608B708C0FBC2F2C4F6CAEFCCEFCE5FD003DE80E0A0E240E47094
:400DC000E602E890ECC01B011F0231203302368037083B40C630CCF0CE103088364037043A023C2088108F0893809F08A520AE80AF41B340CCF0CE60EE4053405640840897
:400E00008C8093809A409E029F04A488A520A6C0B2C0D460E2408E0292029E02A520A6C0AB04AE01EA80EE4015027B02C404DC015940670882108E4191029720AF10B7020E
:400E4000D401D801E008E602EC021A4085408D049102966097289D40A201C608E60209440F4191029420962097299C409D40A201A544A810AB01B040C20FEA0126809202EF
:400E8000A320A520A680AE40B720C820EE405280572079407E01828085208D409202A320A520D460DC80DE20E210E62004200A200C400F401F1050805B405E025F8083408D
:400EC000894091029420962097209C409D40A201AF40B304C001C20DC601D405D605E001E801850188809102A480B3C0E401EA04EC04010109010B010D010F0111011B01BF
:400F00001D0100FF01AB020211050000BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B847004700000100008000000282008200D5
:400F400000000000000303000300000027001801270018010004000000050000000000000000000000000000000000000000000000000000000000000000000000000000DF
:400000000145004009520040015B00400165004047000140380101404E0201404703014046040140440501404C060140490701402C08014031090140040B0140030D014075
:400040006C14014057150140591601404B17014011190140071B01400B400140104101400C4201400F43014002440140054501400A4601400B4701400C480140104901404C
:40008000174C01400C4D014006500140045101407E02080409021082110218021904601561137C402721240A02E40303040E0520064107C00A840B900E840F901001120693
:4000C00013901684179019011A841B481C081DFC1E221F0221C122182324268427902B9C2CE72E10300733E0351F36F83A023B084204460E480449FF4AFF4BFF4F83580B46
:40010000590B5A045B045C995D095F01868088028A8190E7921094019686980F9A409C0F9E20A2E0A618A804AA81AE80B207B4F8D80BDC09DF010022022003010524084089
:4001400009080A080B400C420D200E2010021108130215801610172119011A011C241E201F0C210422082308284029042B88312032643301382039883A013B804240528017
:400180005A215B4A600461016218634278027C028280C06FC2FFC4FDCA07CC0FCE0FD001D60FD80FDE8103140404050806110710081F0A800C010E1E0FE4101F124015102D
:4001C00016E0178218021A111B141C1F1E20211023212408261127142B142D1F2F4032F0330F360F37F03A083B80580B590B5B045C995F018203830884618608873088204C
:4002000089108A508B828DC78E108F2892109304961C97C49A109B04A061A110A204A341A440A630A704AB04AC7CAE02AF04B01FB30FB460B5F4BB08D80BD90BDB04DC99FF
:40024000DF01012A02200301040805400708081009080B8C0C420E200F04104211081504180819221A0C1B011C221D4C1E211F4820042218242025442731285029402B8839
:400280002C022E042F883204331134103508380439813A103D8C3E016230680269806A806D4078027C029308942096E897809C029D249F61A403A50CA620A781AA01AB0889
:4002C000C0EFC2FEC42DCAFFCC67CEDFDE81E208021004400620080C0C010E0210081101140818051A081C04200828202AC02CE02F0130603280341E3501360138203E40ED
:400300005608580459045B045C995D905F0181608209842487108A128B108F10903F93039407950197089B1C9D40A036A209A310A710A82DA901AA12AB04AC40AD7CAF0220
:40034000B11FB238B440B540B607B720BE10D608D80BD90BDB04DC99DD90DF01000201280302040A070409980B800C020E20104212081550170119281A401B401E201FA0A5
:4003800022102662274828022C022E052F043302364237283C203D803F0558805D80600267016B026D106F017C0287208B848F4091409205930496409B209C029F48A0124A
:4003C000A140A208A620A780AD01AE08C07FC23FC4DBCAF8CCF1CEF0D618D818DE80E208E408EA040104020F0440068008700A800C800E200F0110011106130114081602E9
:40040000170218011C0F1EF0200124072608288029052A102B022C082E04310736FF3E403F01580459045B045F018001811C820283E18402852087C0880489828B218C0248
:400440008D088F10900491FF940495089710980599029C049D04A002A1FCA402A520A740A802AC03AE04AF02B007B3FCB503BB20BE01D804D904DB04DC90DF010081012440
:4004800004450520084009080A080B810C080D010E020F041008120113861544172219011C0220042114222C23282740280229012B202D1030083180321033023705396892
:4004C0003A013D82588068066C016D806F048004810184048F0191109220940A9780980299209B019C409F04A401A598A702A880A980AF02C0FFC2FFC4FFCA2BCCCFCE9F8E
:40050000D608E24CE402E605EA04EC02EE0C06010B0410041304160119021C022101240829042C013001310232043304340236083701380239083E553F45560858045904A9
:400540005B045D905F0183018A029501A401AC02B401B501B602B880B920BE50BF10D804D904DB04DF01030804080D800F50100212101410154019101A021E2A1F022210BD
:40058000250226882C802F083308372138023F10584059105DA45E01645266106A406C076D406F09800282C085808608890293409980AF40C022C2B0C4A5CAA0CCA2CE2157
:4005C000D6FCD8F0EA04EE0C9980E208E448EA049980B180E208018002200608070108280B100C020D210E2C1028110F1434152117081828192F1C101E021F2F202821210D
:40060000230224022740282829212B042C202D212E012F0E321F336035803620371F39083E443F1040524720482049FF4AFF4BFF4D204EF05110580459045A045B045C9038
:400640005D095F01610862406340648066406740800F810183028503861087FC88208A018B048C208DFF8E0290039302942395809608970499049A409B209D049E2F9FF9AF
:40068000A023A104A20CA308A423A504A604A740A82FA904AB10AF02B060B3FFB460B61FB822BF04D804D904DB04DC09DF01012202200301040205040608070209880A04D5
:4006C0000B800C080D800E48118012081305144015051610171019881C401D401E041F602118228023112410284129082A102D202E402F6030083240331234013680372A63
:40070000381039423A083C063D803F1041104980510159025A0269806C016D806F0285018D409004914592C2930494429604979199249A089B3B9D40A009A180A22CA548B8
:40074000A722AC02B704C0FFC2FFC47FCAFFCCFFCEFFD004D208E402E808EE1200FF01880403054606FC07B8080C09880A100C0C0EF10F0112081510160417A0180C198849
:400780001A401C011D421E021F04218822022480259A260C2720280C29882A202E022F0431C132FF333F35C137C139A23E043F04580459045B045C905F01800282058521EF
:4007C000870288028C0291279403950896049B389D049F01A118A340A706AC02AF01B006B107B310B401B560B708BE10BF40C006C5ECC803C9FFCAFFCBFFD004D601D8046C
:40080000D904DA04DB04DC99DD09DF01E2C00020010203020406056007100A200C010D800E040F1013801542172819131D042003218022D5240425102605278128102901DB
:400840002A802D202E402F603180321433023680372838043C043D803F11481049104B0264016701684869476A406C02728873068410860194419546978799209B2C9F827A
:40088000A228A448A598A601A722AB40B002B481C0FBC2F4C4F1CAFBCC7FCEF2D204E220E604EA4082108A018E048F029222960197109D209F20A214A302B080B104B6017C
:4008C000E220EA10EC808F209F20AF10B211B520E412EE021B011F083240330836843B408140C630CCF0CE10E62030803204358037083A023D408480914096809740A6046A
:40090000AE80AF01CCF0CE60E210508057208580968897409D809E02A604AB08D460E210EA20832284808E02968097409E02A480A620A720AA24AE04E230E620EC80EE30D9
:400940001501C4045D828740B101D605EE011B04850287108D8097809D82A480A880C608E4020B880C800F108A109798A480A740AB44AF04C20FE404262080018A01974061
:40098000A280A302A620AA40B680C820E620EE8052805302551070017E0190029202A110A280A302AF40B510D4E0DC80DE20EE40052008040E020F801F1053805610588014
:4009C00063028E208F809A109D20A740B120C001C20DC601D407D602E002E402EA04762084809A209C80AF10B004B301B601DE04E801EA08EE01010109010B010D011101C4
:400A00001B0100FF01AB020211050000BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B847004700000100008000000282008200DC
:400A400000000000000707000700000027001801270018010004000000050000000000000000000000000000000000000000000000000000000000000000000000000000D8
:400A80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036
:400AC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F6
:400B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B5
:400B40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075
:400B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035
:400BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F5
:400C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B4
:400C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000074
:400C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034
:400CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F4
:400D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B3
:400D40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073
:400D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033
:400DC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F3
:400E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B2
:400E40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000072
:400E80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000032
:400EC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F2
:400F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1
:400F40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071
:400F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031
:400FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F1
:4010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0
@@ -4615,12 +4615,12 @@
:0200000490105A
:04000000BC90ACAF55
:0200000490303A
:02000000A35308
:02000000F830D6
:0200000490402A
:4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C0
:400040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080
:400080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040
:4000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
:0200000490501A
:0C00000000012E16106900002E31B3BC68
:0C00000000012E16106900002E30089937
:00000001FF

View File

@@ -814,7 +814,7 @@
</Group>
<Group key="Component">
<Group key="v1">
<Data key="cy_boot" value="cy_boot_v5_80" />
<Data key="cy_boot" value="cy_boot_v5_81" />
<Data key="Em_EEPROM_Dynamic" value="Em_EEPROM_Dynamic_v2_20" />
<Data key="LIN_Dynamic" value="LIN_Dynamic_v5_0" />
</Group>
@@ -848,6 +848,7 @@
<Data key="efd5f185-0c32-4824-ba72-3ceb5356f5a7" value="Clock_1" />
</Group>
<Group key="Pin">
<Data key="3e1862bb-be82-47b0-9549-7ebfe76b6f7b" value="Pin_2" />
<Data key="4a398466-709f-4228-9500-96178658e13e" value="RDATA" />
<Data key="5a3407c1-b434-4438-a7b4-b9dfd2280495" value="MOTEA" />
<Data key="8d318d8b-cf7b-4b6b-b02c-ab1c5c49d0ba" value="SW1" />
@@ -858,6 +859,7 @@
<Data key="472f8fdb-f772-44fb-8897-cc690694237b" value="WDATA" />
<Data key="736cb12b-c863-43d4-a8f0-42f06023f8b5" value="SIDE1" />
<Data key="4249c923-fcff-453b-8629-bec6fddd00c1" value="STEP" />
<Data key="27315b0e-6a8c-4b7f-be77-73ab434fa803" value="Pin_1" />
<Data key="1425177d-0d0e-4468-8bcc-e638e5509a9b" value="UartRx" />
<Data key="a5d987c6-e45b-45b9-ad93-656fab06d720" value="TRK00" />
<Data key="a93ef5b3-00f4-42c0-8fad-0e275a7e2537" value="MOTEB" />
@@ -869,6 +871,7 @@
<Data key="c5367cde-21d5-4866-9a32-d16abfea0c61" value="WPT" />
<Data key="d19368c5-6855-41bb-a9ff-808938abef00" value="INDEX" />
<Data key="e9f14b5a-b2bf-49b8-98f3-d7b5a43ace8d" value="DRVSB" />
<Data key="e16b5ef8-00d3-40a4-bc1c-194983c8eb3d" value="LOW_CURRENT" />
<Data key="e851a3b9-efb8-48be-bbb8-b303b216c393" value="INDEX300" />
<Data key="e51063a9-4fad-40c7-a06b-7cc4b137dc18" value="DSKCHG" />
<Data key="ea7ee228-8b3f-426c-8bb8-cd7a81937769" value="DIR" />
@@ -3963,6 +3966,11 @@
</Group>
</Group>
<Group key="Pin2">
<Group key="3e1862bb-be82-47b0-9549-7ebfe76b6f7b">
<Group key="0">
<Data key="Port Format" value="0,6" />
</Group>
</Group>
<Group key="4a398466-709f-4228-9500-96178658e13e">
<Group key="0">
<Data key="Port Format" value="1,5" />
@@ -4064,6 +4072,11 @@
<Data key="Port Format" value="1,0" />
</Group>
</Group>
<Group key="27315b0e-6a8c-4b7f-be77-73ab434fa803">
<Group key="0">
<Data key="Port Format" value="0,7" />
</Group>
</Group>
<Group key="1425177d-0d0e-4468-8bcc-e638e5509a9b">
<Group key="0">
<Data key="Port Format" value="12,6" />
@@ -4149,6 +4162,11 @@
<Data key="Port Format" value="12,3" />
</Group>
</Group>
<Group key="e16b5ef8-00d3-40a4-bc1c-194983c8eb3d">
<Group key="0">
<Data key="Port Format" value="3,2" />
</Group>
</Group>
<Group key="e851a3b9-efb8-48be-bbb8-b303b216c393">
<Group key="0">
<Data key="Port Format" value="3,0" />

View File

@@ -39,20 +39,6 @@
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="crunch.c" persistent="..\lib\common\crunch.c">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="SOURCE_C;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="crunch.h" persistent="..\lib\common\crunch.h">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
</dependencies>
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
@@ -2795,6 +2781,138 @@
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
<filters />
</CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0>
<CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3">
<CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Pin_2" persistent="">
<Hidden v="True" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2">
<dependencies>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Pin_2_aliases.h" persistent="Generated_Source\PSoC5\Pin_2_aliases.h">
<Hidden v="True" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Pin_2.c" persistent="Generated_Source\PSoC5\Pin_2.c">
<Hidden v="True" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="SOURCE_C;CortexM3;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Pin_2.h" persistent="Generated_Source\PSoC5\Pin_2.h">
<Hidden v="True" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
</dependencies>
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
<filters />
</CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0>
<CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3">
<CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Pin_1" persistent="">
<Hidden v="True" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2">
<dependencies>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Pin_1_aliases.h" persistent="Generated_Source\PSoC5\Pin_1_aliases.h">
<Hidden v="True" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Pin_1.c" persistent="Generated_Source\PSoC5\Pin_1.c">
<Hidden v="True" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="SOURCE_C;CortexM3;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Pin_1.h" persistent="Generated_Source\PSoC5\Pin_1.h">
<Hidden v="True" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
</dependencies>
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
<filters />
</CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0>
<CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3">
<CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="TK43_REG" persistent="">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2">
<dependencies>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="TK43_REG.h" persistent="Generated_Source\PSoC5\TK43_REG.h">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="TK43_REG.c" persistent="Generated_Source\PSoC5\TK43_REG.c">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="SOURCE_C;CortexM3;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="TK43_REG_PM.c" persistent="Generated_Source\PSoC5\TK43_REG_PM.c">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="SOURCE_C;CortexM3;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
</dependencies>
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
<filters />
</CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0>
<CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3">
<CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="TK43" persistent="">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2">
<dependencies>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="TK43_aliases.h" persistent="Generated_Source\PSoC5\TK43_aliases.h">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="TK43.c" persistent="Generated_Source\PSoC5\TK43.c">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="SOURCE_C;CortexM3;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1">
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="TK43.h" persistent="Generated_Source\PSoC5\TK43.h">
<Hidden v="False" />
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
<build_action v="HEADER;;;;" />
<PropertyDeltas />
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
</dependencies>
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
<filters />
</CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0>
</dependencies>
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
@@ -3380,6 +3498,6 @@
</ignored_deps>
</CyGuid_495451fe-d201-4d01-b22d-5d3f5609ac37>
<boot_component v="" />
<current_generation v="138" />
<current_generation v="150" />
</CyGuid_fec8f9e8-2365-4bdb-96d3-a4380222e01b>
</CyXmlSerializer>

View File

@@ -1,7 +1,6 @@
//`#start header` -- edit after this line, do not edit this line
`include "cypress.v"
`include "../SuperCounter/SuperCounter.v"
//`#end` -- edit above this line, do not edit this line
// Generated on 12/11/2019 at 21:18
@@ -9,7 +8,7 @@
module Sampler (
output [2:0] debug_state,
output reg [7:0] opcode,
output req,
output reg req,
input clock,
input index,
input rdata,
@@ -19,90 +18,63 @@ module Sampler (
//`#start body` -- edit after this line, do not edit this line
localparam STATE_RESET = 0;
localparam STATE_WAITING = 1;
localparam STATE_OPCODE = 2;
// NOTE: Reset pulse is used in both clock domains, and must be long enough
// to be detected in both.
reg [1:0] state;
reg [6:0] counter;
reg [5:0] counter;
reg oldsampleclock;
wire sampleclocked;
assign sampleclocked = !oldsampleclock && sampleclock;
reg index_q;
reg rdata_q;
reg oldindex;
wire indexed;
assign indexed = !oldindex && index;
reg index_edge;
reg rdata_edge;
wire rdataed;
reg oldrdata;
assign rdataed = !oldrdata && rdata;
reg req_toggle;
assign req = (state == STATE_OPCODE);
always @(posedge clock)
always @(posedge sampleclock)
begin
if (reset)
begin
state <= STATE_RESET;
opcode <= 0;
oldsampleclock <= 0;
oldindex <= 0;
oldrdata <= 0;
index_edge <= 0;
rdata_edge <= 0;
index_q <= 0;
rdata_q <= 0;
counter <= 0;
req_toggle <= 0;
end
else
case (state)
STATE_RESET:
state <= STATE_WAITING;
STATE_WAITING:
begin
/* If something has happened, emit any necessary interval byte. */
if ((rdataed || indexed) && (counter != 0))
begin
opcode <= {0, counter};
state <= STATE_OPCODE;
end
else if (indexed)
begin
oldindex <= 1;
opcode <= 8'h81;
state <= STATE_OPCODE;
end
else if (rdataed)
begin
oldrdata <= 1;
opcode <= 8'h80;
state <= STATE_OPCODE;
end
else if (sampleclocked)
begin
oldsampleclock <= 1;
if (counter == 7'h7f)
begin
opcode <= {0, counter};
state <= STATE_OPCODE;
end
counter <= counter + 1;
end
/* Reset state once we've done the thing. */
if (oldrdata && !rdata)
oldrdata <= 0;
if (oldindex && !index)
oldindex <= 0;
if (oldsampleclock && !sampleclock)
oldsampleclock <= 0;
end
STATE_OPCODE: /* opcode or interval byte sent here */
begin
state <= STATE_WAITING;
counter <= 0;
end
endcase
begin
/* Both index and rdata are active high -- positive-going edges
* indicate the start of an index pulse and read pulse, respectively.
*/
index_edge <= index && !index_q;
index_q <= index;
rdata_edge <= rdata && !rdata_q;
rdata_q <= rdata;
if (rdata_edge || index_edge || (counter == 6'h3f)) begin
opcode <= { rdata_edge, index_edge, counter };
req_toggle <= ~req_toggle;
counter <= 1; /* remember to count this tick */
end else begin
counter <= counter + 1;
end
end
end
reg req_toggle_q;
always @(posedge clock)
begin
if (reset) begin
req_toggle_q <= 0;
req <= 0;
end else begin
req_toggle_q <= req_toggle;
req <= (req_toggle != req_toggle_q);
end
end
//`#end` -- edit above this line, do not edit this line

View File

@@ -19,19 +19,15 @@ module Sequencer (
//`#start body` -- edit after this line, do not edit this line
localparam STATE_LOAD = 0;
localparam STATE_WAITING = 1;
localparam STATE_PULSING = 2;
localparam STATE_INDEXING = 3;
localparam STATE_WRITING = 1;
localparam OPCODE_PULSE = 8'h80;
localparam OPCODE_INDEX = 8'h81;
reg [1:0] state;
reg [6:0] countdown;
reg state;
reg [5:0] countdown;
reg pulsepending;
assign req = (!reset && (state == STATE_LOAD));
assign wdata = (state == STATE_PULSING);
assign debug_state = state;
assign wdata = (!reset && (state == STATE_WRITING) && (countdown == 0) && pulsepending);
assign debug_state = 0;
reg olddataclock;
wire dataclocked;
@@ -52,49 +48,43 @@ begin
begin
state <= STATE_LOAD;
countdown <= 0;
pulsepending <= 0;
oldsampleclock <= 0;
end
else
begin
if (!oldsampleclock && sampleclock)
sampleclocked <= 1;
oldsampleclock <= sampleclock;
case (state)
STATE_LOAD:
/* Wait for a posedge on dataclocked, indicating an opcode has
begin
/* A posedge on dataclocked indicates that another opcode has
* arrived. */
if (dataclocked)
case (opcode)
OPCODE_PULSE:
state <= STATE_PULSING;
OPCODE_INDEX:
state <= STATE_INDEXING;
default:
begin
countdown <= opcode[6:0];
state <= STATE_WAITING;
end
endcase
begin
pulsepending <= opcode[7];
if (opcode[5:0] == 0)
countdown <= 0;
else
countdown <= opcode[5:0] - 1; /* compensate for extra tick in state machine */
state <= STATE_WRITING;
end
end
STATE_WAITING:
STATE_WRITING:
begin
if (sampleclocked)
begin
sampleclocked <= 0;
countdown <= countdown - 1;
/* Nasty fudge factor here to account for one to two
* sample ticks lost per pulse. */
if (countdown <= 2)
if (countdown == 0)
state <= STATE_LOAD;
else
countdown <= countdown - 1;
sampleclocked <= 0;
end
STATE_PULSING:
state <= STATE_LOAD;
STATE_INDEXING:
if (indexed)
state <= STATE_LOAD;
end
endcase
end
end

View File

Binary file not shown.

View File

@@ -5,7 +5,6 @@
#include <setjmp.h>
#include "project.h"
#include "../protocol.h"
#include "../lib/common/crunch.h"
#define MOTOR_ON_TIME 5000 /* milliseconds */
#define STEP_INTERVAL_TIME 6 /* ms */
@@ -14,11 +13,18 @@
#define DISKSTATUS_WPT 1
#define DISKSTATUS_DSKCHG 2
#define STEP_TOWARDS0 1
#define STEP_AWAYFROM0 0
#define STEP_TOWARDS0 0
#define STEP_AWAYFROM0 1
static bool drive0_present;
static bool drive1_present;
static volatile uint32_t clock = 0; /* ms */
static volatile bool index_irq = false;
/* Duration in ms. 0 causes every pulse to be an index pulse. Durations since
* last pulse greater than this value imply sector pulse. Otherwise is an index
* pulse. */
static volatile uint32_t hardsec_index_threshold = 0;
static bool motor_on = false;
static uint32_t motor_on_time = 0;
@@ -31,7 +37,6 @@ static struct set_drive_frame current_drive_flags;
static uint8_t td[BUFFER_COUNT];
static uint8_t dma_buffer[BUFFER_COUNT][BUFFER_SIZE] __attribute__((aligned()));
static uint8_t usb_buffer[BUFFER_SIZE] __attribute__((aligned()));
static uint8_t xfer_buffer[BUFFER_SIZE] __attribute__((aligned()));
static uint8_t dma_channel;
#define NEXT_BUFFER(b) (((b)+1) % BUFFER_COUNT)
@@ -42,6 +47,8 @@ static volatile bool dma_underrun = false;
#define DECLARE_REPLY_FRAME(STRUCT, TYPE) \
STRUCT r = {.f = { .type = TYPE, .size = sizeof(STRUCT) }}
static void stop_motor(void);
static void system_timer_cb(void)
{
CyGlobalIntDisable;
@@ -66,12 +73,34 @@ static void system_timer_cb(void)
CY_ISR(index_irq_cb)
{
index_irq = true;
/* Hard sectored media has sector pulses at the beginning of every sector
* and the index pulse is an extra pulse in the middle of the last sector.
* When the extra pulse is seen, the next sector pulse is also the start of
* the track. */
static bool hardsec_index_irq_primed = false;
static uint32_t hardsec_last_pulse_time = 0;
if (!hardsec_index_threshold)
{
index_irq = true;
hardsec_index_irq_primed = false;
}
else
{
index_irq = hardsec_index_irq_primed;
if (index_irq)
hardsec_index_irq_primed = false;
else
hardsec_index_irq_primed =
clock - hardsec_last_pulse_time <= hardsec_index_threshold;
hardsec_last_pulse_time = clock;
}
/* Stop writing the instant the index pulse comes along; it may take a few
* moments for the main code to notice the pulse, and we don't want to overwrite
* the beginning of the track. */
ERASE_REG_Write(0);
if (index_irq)
ERASE_REG_Write(0);
}
CY_ISR(capture_dma_finished_irq_cb)
@@ -104,7 +133,10 @@ static void print(const char* msg, ...)
static void set_drive_flags(struct set_drive_frame* flags)
{
if (current_drive_flags.drive != flags->drive)
{
stop_motor();
homed = false;
}
current_drive_flags = *flags;
DRIVESELECT_REG_Write(flags->drive ? 2 : 1); /* select drive 1 or 0 */
@@ -143,6 +175,12 @@ static void wait_until_writeable(int ep)
;
}
static void wait_until_readable(int ep)
{
while (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_FULL)
;
}
static void send_reply(struct any_frame* f)
{
print("reply 0x%02x", f->f.type);
@@ -160,9 +198,15 @@ static void send_error(int code)
/* buffer must be big enough for a frame */
static int usb_read(int ep, uint8_t buffer[FRAME_SIZE])
{
if (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_FULL)
{
USBFS_EnableOutEP(ep);
wait_until_readable(ep);
}
int length = USBFS_GetEPCount(ep);
USBFS_ReadOutEP(ep, buffer, length);
while (USBFS_GetEPState(ep) == USBFS_OUT_BUFFER_FULL)
while (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_EMPTY)
;
return length;
}
@@ -184,19 +228,19 @@ static void step(int dir)
CyDelay(STEP_INTERVAL_TIME);
}
static void home(void)
/* returns true if it looks like a drive is attached */
static bool home(void)
{
for (int i=0; i<100; i++)
{
/* Don't keep stepping forever, because if a drive's
* not connected bad things happen. */
if (TRACK0_REG_Read())
break;
return true;
step(STEP_TOWARDS0);
}
/* Step to -1, which should be a nop, to reset the disk on disk change. */
step(STEP_TOWARDS0);
return false;
}
static void seek_to(int track)
@@ -231,6 +275,8 @@ static void seek_to(int track)
CyWdtClear();
}
CyDelay(STEP_SETTLING_TIME);
TK43_REG_Write(track < 43); /* high if 0..42, low if 43 or up */
print("finished seek");
}
@@ -249,7 +295,7 @@ static void cmd_recalibrate(void)
send_reply(&r);
}
static void cmd_measure_speed(struct any_frame* f)
static void cmd_measure_speed(struct measurespeed_frame* f)
{
start_motor();
@@ -268,10 +314,14 @@ static void cmd_measure_speed(struct any_frame* f)
if (elapsed != 0)
{
index_irq = false;
int target_pulse_count = f->hard_sector_count + 1;
start_clock = clock;
while (!index_irq)
elapsed = clock - start_clock;
for (int x=0; x<target_pulse_count; x++)
{
index_irq = false;
while (!index_irq)
elapsed = clock - start_clock;
}
}
DECLARE_REPLY_FRAME(struct speed_frame, F_FRAME_MEASURE_SPEED_REPLY);
@@ -311,13 +361,7 @@ static void cmd_bulk_read_test(struct any_frame* f)
CyWdtClear();
for (int y=0; y<256; y++)
{
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_FULL)
;
USBFS_ReadOutEP(FLUXENGINE_DATA_OUT_EP_NUM, buffer, sizeof(buffer));
while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_EMPTY)
;
usb_read(FLUXENGINE_DATA_OUT_EP_NUM, buffer);
for (unsigned z=0; z<sizeof(buffer); z++)
{
if (buffer[z] != (uint8)(x+y+z))
@@ -348,7 +392,7 @@ static void deinit_dma(void)
static void init_capture_dma(void)
{
dma_channel = SAMPLER_DMA_DmaInitialize(
2 /* bytes */,
1 /* bytes */,
true /* request per burst */,
HI16(CYDEV_PERIPH_BASE),
HI16(CYDEV_SRAM_BASE));
@@ -369,8 +413,9 @@ static void init_capture_dma(void)
static void cmd_read(struct read_frame* f)
{
SIDE_REG_Write(f->side);
seek_to(current_track);
SIDE_REG_Write(f->side);
STEP_REG_Write(f->side); /* for drives which multiplex SIDE and DIR */
/* Do slow setup *before* we go into the real-time bit. */
@@ -389,16 +434,14 @@ static void cmd_read(struct read_frame* f)
if (f->synced)
{
hardsec_index_threshold = f->hardsec_threshold_ms;
index_irq = false;
while (!index_irq)
;
index_irq = false;
hardsec_index_threshold = 0;
}
crunch_state_t cs = {};
cs.outputptr = xfer_buffer;
cs.outputlen = BUFFER_SIZE;
dma_writing_to_td = 0;
dma_reading_from_td = -1;
dma_underrun = false;
@@ -455,54 +498,22 @@ static void cmd_read(struct read_frame* f)
{
/* Otherwise, there's a block waiting, so attempt to send it. */
uint8_t dma_buffer_usage = 0;
while (dma_buffer_usage < BUFFER_SIZE)
{
cs.inputptr = dma_buffer[dma_reading_from_td] + dma_buffer_usage;
cs.inputlen = BUFFER_SIZE - dma_buffer_usage;
crunch(&cs);
dma_buffer_usage += BUFFER_SIZE - cs.inputlen;
count++;
/* If there is no available space in the output buffer, flush the buffer via
* USB and go again. */
if (cs.outputlen == 0)
{
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
memcpy(usb_buffer, xfer_buffer, FRAME_SIZE);
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE);
cs.outputptr = xfer_buffer;
cs.outputlen = BUFFER_SIZE;
}
}
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, dma_buffer[dma_reading_from_td], BUFFER_SIZE);
count++;
dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td);
}
}
abort:;
bool saved_dma_underrun = dma_underrun;
donecrunch(&cs);
/* Terminate the transfer (all transfers are an exact number of fragments). */
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
/* If there's a complete packet waiting, send it. */
if (cs.outputlen != BUFFER_SIZE)
{
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE);
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
}
if ((cs.outputlen != 0) && (cs.outputlen != BUFFER_SIZE))
{
/* If there's a partial packet waiting, send it; this will also terminate the transfer. */
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen);
}
else
{
/* Otherwise just terminate the transfer. */
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0);
}
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0);
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
deinit_dma();
STEP_REG_Write(0);
if (saved_dma_underrun)
{
print("underrun after %d packets");
@@ -548,9 +559,11 @@ static void cmd_write(struct write_frame* f)
return;
}
SEQUENCER_CONTROL_Write(1); /* put the sequencer into reset */
seek_to(current_track);
SIDE_REG_Write(f->side);
STEP_REG_Write(f->side); /* for drives which multiplex SIDE and DIR */
SEQUENCER_CONTROL_Write(1); /* put the sequencer into reset */
{
uint8_t i = CyEnterCriticalSection();
REPLAY_FIFO_SET_LEVEL_MID;
@@ -558,41 +571,21 @@ static void cmd_write(struct write_frame* f)
REPLAY_FIFO_SINGLE_BUFFER_UNSET;
CyExitCriticalSection(i);
}
seek_to(current_track);
init_replay_dma();
bool writing = false; /* to the disk */
bool finished = false;
int packets = f->bytes_to_write / FRAME_SIZE;
bool finished = (packets == 0);
int count_written = 0;
int count_read = 0;
int packetwaiting = 0;
dma_writing_to_td = 0;
dma_reading_from_td = -1;
dma_underrun = false;
crunch_state_t cs = {};
cs.outputlen = BUFFER_SIZE;
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
int old_reading_from_td = -1;
for (;;)
{
CyWdtClear();
/* Make sure that we always have a USB read in progress whenever possible. */
if (!finished && !packetwaiting)
{
/* There is no read in progress; has data arrived in the external USB buffer? */
if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_FULL)
{
/* Yes, data has arrived, so initiate the copy. */
packetwaiting = USBFS_ReadOutEP(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer, FRAME_SIZE);
}
}
//CyWdtClear();
/* Read data from USB into the buffers. */
@@ -601,59 +594,22 @@ static void cmd_write(struct write_frame* f)
if (writing && (dma_underrun || index_irq))
goto abort;
/* Read crunched data, if necessary. */
if (cs.inputlen == 0)
uint8_t* buffer = dma_buffer[dma_writing_to_td];
if (finished)
{
if (finished)
{
/* There's no more data to read, so fake some. */
for (int i=0; i<BUFFER_SIZE; i++)
xfer_buffer[i+0] = 0x7f;
cs.inputptr = xfer_buffer;
cs.inputlen = BUFFER_SIZE;
}
else if (packetwaiting)
{
/* There's a USB read into usb_buffer in progress, so check if it's finished. */
if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_EMPTY)
{
/* It's done, so copy out the data. */
memcpy(xfer_buffer, usb_buffer, FRAME_SIZE);
cs.inputptr = xfer_buffer;
cs.inputlen = packetwaiting;
count_read++;
if ((packetwaiting < FRAME_SIZE) || (count_read == packets))
finished = true;
else
{
/* Wait for more USB data to show up. */
packetwaiting = 0;
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
}
}
}
/* There's no more data to read, so fake some. */
memset(buffer, 0x3f, BUFFER_SIZE);
}
/* If there *is* data waiting in the buffer, uncrunch it. */
if (cs.inputlen != 0)
else
{
cs.outputptr = dma_buffer[dma_writing_to_td] + BUFFER_SIZE - cs.outputlen;
uncrunch(&cs);
if (cs.outputlen == 0)
{
/* Completed a DMA buffer; queue it for writing. */
dma_writing_to_td = NEXT_BUFFER(dma_writing_to_td);
cs.outputlen = BUFFER_SIZE;
}
(void) usb_read(FLUXENGINE_DATA_OUT_EP_NUM, buffer);
count_read++;
if (count_read == packets)
finished = true;
}
dma_writing_to_td = NEXT_BUFFER(dma_writing_to_td);
/* Once all the buffers are full, start writing. */
@@ -672,6 +628,7 @@ static void cmd_write(struct write_frame* f)
/* Wait for the index marker. While this happens, the DMA engine
* will prime the FIFO. */
hardsec_index_threshold = f->hardsec_threshold_ms;
index_irq = false;
while (!index_irq)
;
@@ -693,7 +650,6 @@ static void cmd_write(struct write_frame* f)
}
}
abort:
print("done %d %d", dma_reading_from_td, dma_writing_to_td);
SEQUENCER_DMA_FINISHED_IRQ_Disable();
SEQUENCER_CONTROL_Write(1); /* reset */
@@ -707,33 +663,29 @@ abort:
}
print("p=%d cr=%d cw=%d f=%d w=%d index=%d underrun=%d", packets, count_read, count_written, finished, writing, index_irq, dma_underrun);
hardsec_index_threshold = 0;
if (!finished)
{
/* There's still some data to read, so just read and blackhole it ---
* easier than trying to terminate the connection. */
while (count_read != packets)
{
if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_FULL)
{
int length = usb_read(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer);
if (length < FRAME_SIZE)
break;
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
count_read++;
}
(void) usb_read(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer);
count_read++;
}
USBFS_DisableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
}
deinit_dma();
print("write finished");
STEP_REG_Write(0);
if (dma_underrun)
{
print("underrun!");
send_error(F_ERROR_UNDERRUN);
return;
}
print("success");
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_WRITE_REPLY);
send_reply((struct any_frame*) &r);
}
@@ -745,6 +697,7 @@ static void cmd_erase(struct erase_frame* f)
/* Disk is now spinning. */
print("start erasing");
hardsec_index_threshold = f->hardsec_threshold_ms;
index_irq = false;
while (!index_irq)
;
@@ -753,6 +706,7 @@ static void cmd_erase(struct erase_frame* f)
while (!index_irq)
;
ERASE_REG_Write(0);
hardsec_index_threshold = 0;
print("stop erasing");
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_ERASE_REPLY);
@@ -761,6 +715,10 @@ static void cmd_erase(struct erase_frame* f)
static void cmd_set_drive(struct set_drive_frame* f)
{
if (drive0_present && !drive1_present)
f->drive = 0;
if (drive1_present && !drive0_present)
f->drive = 1;
set_drive_flags(f);
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_SET_DRIVE_REPLY);
@@ -874,7 +832,7 @@ static void handle_command(void)
break;
case F_FRAME_MEASURE_SPEED_CMD:
cmd_measure_speed(f);
cmd_measure_speed((struct measurespeed_frame*) f);
break;
case F_FRAME_BULK_WRITE_TEST_CMD:
@@ -914,6 +872,21 @@ static void handle_command(void)
}
}
static void detect_drives(void)
{
current_drive_flags.drive = 0;
start_motor();
drive0_present = home();
stop_motor();
current_drive_flags.drive = 1;
start_motor();
drive1_present = home();
stop_motor();
print("drive 0: %s drive 1: %s", drive0_present ? "yes" : "no", drive1_present ? "yes" : "no");
}
int main(void)
{
CyGlobalIntEnable;
@@ -927,11 +900,11 @@ int main(void)
DRIVESELECT_REG_Write(0);
UART_Start();
USBFS_Start(0, USBFS_DWR_VDDD_OPERATION);
USBFS_DisableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
detect_drives();
CyWdtStart(CYWDT_1024_TICKS, CYWDT_LPMODE_DISABLED);
/* UART_PutString("GO\r"); */
for (;;)
{
CyWdtClear();
@@ -947,7 +920,7 @@ int main(void)
{
print("Waiting for USB...");
while (!USBFS_GetConfiguration())
;
CyWdtClear();
print("USB ready");
USBFS_EnableOutEP(FLUXENGINE_CMD_OUT_EP_NUM);
}

View File

@@ -39,7 +39,7 @@ CFLAGS += -Ilib -Idep/fmt -Iarch
export OBJDIR = .obj
all: .obj/build.ninja
@ninja -f .obj/build.ninja -v
@ninja -f .obj/build.ninja
clean:
@echo CLEAN

View File

@@ -24,17 +24,18 @@ Don't believe me? Watch the demo reel!
<iframe width="373" height="210" src="https://www.youtube.com/embed/m_s1iw8eW7o" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
**Important note.** On 2019-02-09 I did a hardware redesign and moved the pins on
the board. Sorry for the inconvenience, but it means you don't have to modify
the board any more to make it work. If you built the hardware prior to then,
you'll need to adjust it.
**New!** The FluxEngine client software now works with
[GreaseWeazle](https://github.com/keirf/Greaseweazle/wiki) hardware. So, if you
can't find a PSoC5 development kit, or don't want to use the Cypress Windows
tools for programming it, you can use one of these instead. Very nearly all
FluxEngine features are available with the GreaseWeazle and it works out-of-the
box. See the [dedicated GreaseWeazle documentation page](doc/greaseweazle.md)
for more information.
**Another important note.** On 2019-07-03 I've revamped the build process and
the (command line) user interface. It should be much nicer now, not least in
that there's a single client binary with all the functionality in it. The
interface is a little different, but not much. The build process is now
better (simpler). See [the building](doc/building.md) and
[using](doc/using.md) pages for more details.
**Important note.** On 2020-04-02 I changed the bytecode format (and firmware).
Flux files will need to be upgraded with `fluxengine upgradefluxfile`. The new
format should be more reliable and use way, way less bandwidth. Sorry for the
inconvenience.
Where?
------
@@ -59,8 +60,15 @@ following friendly articles:
- [Using a FluxEngine](doc/using.md) ∾ what to do with your new hardware ∾
flux files and image files ∾ knowing what you're doing
- [Troubleshooting dubious disks](doc/problems.md) ∾ it's not an exact science ∾
the sector map ∾ clock detection and the histogram
- [Using GreaseWeazle hardware with the FluxEngine client
software](doc/greaseweazle.md) ∾ what works ∾ what doesn't work ∾ where to
go for help
- [Troubleshooting dubious disks](doc/problems.md) ∾ it's not an exact
science ∾ the sector map ∾ clock detection and the histogram
- [Checking your drive](doc/driveresponse.md) ∾ you can't do that with that ∾
measuring your drive's ability to work with exotic formats
Which?
------
@@ -89,7 +97,7 @@ people who've had it work).
| [Brother 120kB](doc/disk-brother.md) | 🦄 | | |
| [Brother 240kB](doc/disk-brother.md) | 🦄 | 🦄 | |
| [Brother FB-100](doc/disk-fb100.md) | 🦖 | | Tandy Model 100, Husky Hunter, knitting machines |
| [Macintosh 800kB](doc/disk-macintosh.md) | 🦖 | | and probably the 400kB too |
| [Macintosh 800kB](doc/disk-macintosh.md) | 🦄 | 🦄 | and probably the 400kB too |
| [TRS-80](doc/disk-trs80.md) | 🦖 | 🦖* | a minor variation of the IBM scheme |
{: .datatable }
@@ -110,8 +118,10 @@ at least, check the CRC so what data's there is probably good.
| [AES Superplus / No Problem](doc/disk-aeslanier.md) | 🦖 | | hard sectors! |
| [Durango F85](doc/disk-durangof85.md) | 🦖 | | 5.25" |
| [DVK MX](doc/disk-mx.md) | 🦖 | | Soviet PDP-11 clone |
| [Victor 9000](doc/disk-victor9k.md) | 🦖 | | 8-inch |
| [Zilog MCZ](doc/disk-zilogmcz.md) | 🦖 | | 8-inch _and_ hard sectors |
| [Micropolis](doc/disk-micropolis.md) | 🦄 | | Micropolis 100tpi drives |
| [TI DS990 FD1000](doc/disk-tids990.md) | 🦄 | 🦄 | 8" |
| [Victor 9000](doc/disk-victor9k.md) | 🦖 | | 8" |
| [Zilog MCZ](doc/disk-zilogmcz.md) | 🦖 | | 8" _and_ hard sectors |
{: .datatable }
### Notes
@@ -195,6 +205,17 @@ contributions from many other people. It is licensed under the terms of the
BSD license. Please see the contents of the directory for the full text.
As an exception, `dep/emu` contains parts of the OpenBSD C library
code, Todd Miller and William A. Rowe (and probably others). It is licensed
code, maintained by Todd Miller and William A. Rowe (and probably others). It is licensed
under the terms of the 3-clause BSD license. Please see the contents of the
directory for the full text. It's been lightly modified by me.
As an exception, `dep/agg` contains parts of the Anti-Grain Antialiasing
library, written by Maxim Semanarev (and others). It is licensed under the
terms of the 3-clause BSD license. Please see the contents of the directory for
the full text. It's been lightly modified by me.
As an exception, `dep/stb` contains parts of the libstb utility library,
written by Sean T Barett (and others). It is public domain/Unlicense/MIT
licensed, at your choice. Please see the contents of the directory for the full
text.

View File

@@ -20,6 +20,8 @@ public:
RecordType advanceToNextRecord();
void decodeSectorRecord();
std::set<unsigned> requiredSectors(Track& track) const;
};
class AmigaEncoder : public AbstractEncoder

View File

@@ -32,6 +32,8 @@ AbstractDecoder::RecordType AmigaDecoder::advanceToNextRecord()
void AmigaDecoder::decodeSectorRecord()
{
const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16);
if (rawbits.size() < (AMIGA_RECORD_SIZE*16))
return;
const auto& rawbytes = toBytes(rawbits).slice(0, AMIGA_RECORD_SIZE*2);
const auto& bytes = decodeFmMfm(rawbits).slice(0, AMIGA_RECORD_SIZE);
@@ -56,3 +58,10 @@ void AmigaDecoder::decodeSectorRecord()
_sector->data.writer().append(amigaDeinterleave(ptr, 512)).append(recoveryinfo);
_sector->status = (gotdatachecksum == wanteddatachecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
}
std::set<unsigned> AmigaDecoder::requiredSectors(Track& track) const
{
static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return sectors;
}

View File

@@ -9,7 +9,8 @@
#define BROTHER_DATA_RECORD_CHECKSUM 3
#define BROTHER_DATA_RECORD_ENCODED_SIZE 415
#define BROTHER_TRACKS_PER_DISK 78
#define BROTHER_TRACKS_PER_240KB_DISK 78
#define BROTHER_TRACKS_PER_120KB_DISK 39
#define BROTHER_SECTORS_PER_TRACK 12
class Sector;
@@ -28,8 +29,16 @@ public:
class BrotherEncoder : public AbstractEncoder
{
public:
BrotherEncoder(int format, int bias):
_format(format),
_bias(bias)
{}
virtual ~BrotherEncoder() {}
private:
int _format;
int _bias;
public:
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
};

View File

@@ -129,9 +129,25 @@ static int charToInt(char c)
std::unique_ptr<Fluxmap> BrotherEncoder::encode(
int physicalTrack, int physicalSide, const SectorSet& allSectors)
{
if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_DISK)
|| (physicalSide != 0))
int logicalTrack;
if (physicalSide != 0)
return std::unique_ptr<Fluxmap>();
physicalTrack -= _bias;
switch (_format)
{
case 120:
if ((physicalTrack < 0) || (physicalTrack >= (BROTHER_TRACKS_PER_120KB_DISK*2))
|| (physicalTrack & 1))
return std::unique_ptr<Fluxmap>();
logicalTrack = physicalTrack/2;
break;
case 240:
if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK))
return std::unique_ptr<Fluxmap>();
logicalTrack = physicalTrack;
break;
}
int bitsPerRevolution = 200000.0 / clockRateUs;
const std::string& skew = sectorSkew.get();
@@ -146,10 +162,10 @@ std::unique_ptr<Fluxmap> BrotherEncoder::encode(
double dataMs = headerMs + postHeaderSpacingMs;
unsigned dataCursor = dataMs*1e3 / clockRateUs;
const auto& sectorData = allSectors.get(physicalTrack, 0, sectorId);
const auto& sectorData = allSectors.get(logicalTrack, 0, sectorId);
fillBitmapTo(bits, cursor, headerCursor, { true, false });
write_sector_header(bits, cursor, physicalTrack, sectorId);
write_sector_header(bits, cursor, logicalTrack, sectorId);
fillBitmapTo(bits, cursor, dataCursor, { true, false });
write_sector_data(bits, cursor, sectorData->data);
}

View File

@@ -57,11 +57,11 @@ const FluxPattern FM_TRS80DAM1_PATTERN(16, 0xf56b);
/*
* TRS80DAM2 record:
* flux: XXXX-X-X-XX-XXX- = 0xf56c
* flux: XXXX-X-X-XX-XXX- = 0xf56e
* clock: X X - - - X X X = 0xc7
* data: X X X X X - X - = 0xfa
*/
const FluxPattern FM_TRS80DAM2_PATTERN(16, 0xf56c);
const FluxPattern FM_TRS80DAM2_PATTERN(16, 0xf56e);
/* MFM record separator:
* 0xA1 is:

View File

@@ -102,6 +102,8 @@ static uint8_t decodeUint16(uint16_t raw)
std::unique_ptr<Fluxmap> IbmEncoder::encode(
int physicalTrack, int physicalSide, const SectorSet& allSectors)
{
if (_parameters.swapSides)
physicalSide = 1 - physicalSide;
double clockRateUs = 1e3 / _parameters.clockRateKhz;
if (!_parameters.useFm)
clockRateUs /= 2.0;

View File

@@ -32,18 +32,24 @@ struct IbmIdam
class IbmDecoder : public AbstractDecoder
{
public:
IbmDecoder(unsigned sectorBase, bool ignoreSideByte=false):
IbmDecoder(unsigned sectorBase, bool ignoreSideByte=false,
const std::set<unsigned> requiredSectors=std::set<unsigned>()):
_sectorBase(sectorBase),
_ignoreSideByte(ignoreSideByte)
_ignoreSideByte(ignoreSideByte),
_requiredSectors(requiredSectors)
{}
RecordType advanceToNextRecord();
void decodeSectorRecord();
void decodeDataRecord();
std::set<unsigned> requiredSectors(Track& track) const
{ return _requiredSectors; }
private:
unsigned _sectorBase;
bool _ignoreSideByte;
std::set<unsigned> _requiredSectors;
unsigned _currentSectorSize;
unsigned _currentHeaderLength;
};
@@ -63,6 +69,7 @@ struct IbmParameters
int gap2;
int gap3;
std::string sectorSkew;
bool swapSides;
};
class IbmEncoder : public AbstractEncoder

View File

@@ -118,10 +118,10 @@ static Bytes decode_crazy_data(const Bytes& input, Sector::Status& status)
uint8_t decode_side(uint8_t side)
{
/* Mac disks, being weird, use the side byte to encode both the side (in
* bit 5) and also whether we're above track 0x3f (in bit 6).
* bit 5) and also whether we're above track 0x3f (in bit 0).
*/
return !!(side & 0x40);
return !!(side & 0x20);
}
AbstractDecoder::RecordType MacintoshDecoder::advanceToNextRecord()
@@ -184,3 +184,25 @@ void MacintoshDecoder::decodeDataRecord()
_sector->data.clear();
_sector->data.writer().append(userData.slice(12, 512)).append(userData.slice(0, 12));
}
std::set<unsigned> MacintoshDecoder::requiredSectors(Track& track) const
{
int count;
if (track.physicalTrack < 16)
count = 12;
else if (track.physicalTrack < 32)
count = 11;
else if (track.physicalTrack < 48)
count = 10;
else if (track.physicalTrack < 64)
count = 9;
else
count = 8;
std::set<unsigned> sectors;
while (count--)
sectors.insert(count);
return sectors;
}

242
arch/macintosh/encoder.cc Normal file
View File

@@ -0,0 +1,242 @@
#include "globals.h"
#include "record.h"
#include "decoders/decoders.h"
#include "encoders/encoders.h"
#include "macintosh.h"
#include "crc.h"
#include "sectorset.h"
#include "writer.h"
#include "fmt/format.h"
#include <ctype.h>
FlagGroup macintoshEncoderFlags;
static DoubleFlag postIndexGapUs(
{ "--post-index-gap-us" },
"Post-index gap before first sector header (microseconds).",
0);
static DoubleFlag clockCompensation(
{ "--clock-compensation-factor" },
"Scale the output clock by this much.",
1.0);
static bool lastBit;
static double clockRateUsForTrack(unsigned track)
{
if (track < 16)
return 2.623;
if (track < 32)
return 2.861;
if (track < 48)
return 3.148;
if (track < 64)
return 3.497;
return 3.934;
}
static unsigned sectorsForTrack(unsigned track)
{
if (track < 16)
return 12;
if (track < 32)
return 11;
if (track < 48)
return 10;
if (track < 64)
return 9;
return 8;
}
static int encode_data_gcr(uint8_t gcr)
{
switch (gcr)
{
#define GCR_ENTRY(gcr, data) \
case data: return gcr;
#include "data_gcr.h"
#undef GCR_ENTRY
}
return -1;
};
/* This is extremely inspired by the MESS implementation, written by Nathan Woods
* and R. Belmont: https://github.com/mamedev/mame/blob/4263a71e64377db11392c458b580c5ae83556bc7/src/lib/formats/ap_dsk35.cpp
*/
static Bytes encode_crazy_data(const Bytes& input)
{
Bytes output;
ByteWriter bw(output);
ByteReader br(input);
uint8_t w1, w2, w3, w4;
static const int LOOKUP_LEN = MAC_SECTOR_LENGTH / 3;
uint8_t b1[LOOKUP_LEN + 1];
uint8_t b2[LOOKUP_LEN + 1];
uint8_t b3[LOOKUP_LEN + 1];
uint32_t c1 = 0;
uint32_t c2 = 0;
uint32_t c3 = 0;
for (int j=0;; j++)
{
c1 = (c1 & 0xff) << 1;
if (c1 & 0x0100)
c1++;
uint8_t val = br.read_8();
c3 += val;
if (c1 & 0x0100)
{
c3++;
c1 &= 0xff;
}
b1[j] = (val ^ c1) & 0xff;
val = br.read_8();
c2 += val;
if (c3 > 0xff)
{
c2++;
c3 &= 0xff;
}
b2[j] = (val ^ c3) & 0xff;
if (br.pos == 524)
break;
val = br.read_8();
c1 += val;
if (c2 > 0xff)
{
c1++;
c2 &= 0xff;
}
b3[j] = (val ^ c2) & 0xff;
}
uint32_t c4 = ((c1 & 0xc0) >> 6) | ((c2 & 0xc0) >> 4) | ((c3 & 0xc0) >> 2);
b3[LOOKUP_LEN] = 0;
for (int i = 0; i <= LOOKUP_LEN; i++)
{
w1 = b1[i] & 0x3f;
w2 = b2[i] & 0x3f;
w3 = b3[i] & 0x3f;
w4 = ((b1[i] & 0xc0) >> 2);
w4 |= ((b2[i] & 0xc0) >> 4);
w4 |= ((b3[i] & 0xc0) >> 6);
bw.write_8(w4);
bw.write_8(w1);
bw.write_8(w2);
if (i != LOOKUP_LEN)
bw.write_8(w3);
}
bw.write_8(c4 & 0x3f);
bw.write_8(c3 & 0x3f);
bw.write_8(c2 & 0x3f);
bw.write_8(c1 & 0x3f);
return output;
}
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vector<bool>& src)
{
for (bool bit : src)
{
if (cursor < bits.size())
bits[cursor++] = bit;
}
}
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width)
{
cursor += width;
for (int i=0; i<width; i++)
{
unsigned pos = cursor - i - 1;
if (pos < bits.size())
bits[pos] = data & 1;
data >>= 1;
}
}
static uint8_t encode_side(uint8_t track, uint8_t side)
{
/* Mac disks, being weird, use the side byte to encode both the side (in
* bit 5) and also whether we're above track 0x3f (in bit 0).
*/
return (side ? 0x20 : 0x00) | ((track>0x3f) ? 0x01 : 0x00);
}
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
{
if ((sector->data.size() != 512) && (sector->data.size() != 524))
Error() << "unsupported sector size --- you must pick 512 or 524";
write_bits(bits, cursor, 0xff, 1*8); /* pad byte */
for (int i=0; i<7; i++)
write_bits(bits, cursor, 0xff3fcff3fcffLL, 6*8); /* sync */
write_bits(bits, cursor, MAC_SECTOR_RECORD, 3*8);
uint8_t encodedTrack = sector->physicalTrack & 0x3f;
uint8_t encodedSector = sector->logicalSector;
uint8_t encodedSide = encode_side(sector->physicalTrack, sector->logicalSide);
uint8_t formatByte = MAC_FORMAT_BYTE;
uint8_t headerChecksum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f;
write_bits(bits, cursor, encode_data_gcr(encodedTrack), 1*8);
write_bits(bits, cursor, encode_data_gcr(encodedSector), 1*8);
write_bits(bits, cursor, encode_data_gcr(encodedSide), 1*8);
write_bits(bits, cursor, encode_data_gcr(formatByte), 1*8);
write_bits(bits, cursor, encode_data_gcr(headerChecksum), 1*8);
write_bits(bits, cursor, 0xdeaaff, 3*8);
write_bits(bits, cursor, 0xff3fcff3fcffLL, 6*8); /* sync */
write_bits(bits, cursor, MAC_DATA_RECORD, 3*8);
write_bits(bits, cursor, encode_data_gcr(sector->logicalSector), 1*8);
Bytes wireData;
wireData.writer().append(sector->data.slice(512, 12)).append(sector->data.slice(0, 512));
for (uint8_t b : encode_crazy_data(wireData))
write_bits(bits, cursor, encode_data_gcr(b), 1*8);
write_bits(bits, cursor, 0xdeaaff, 3*8);
}
std::unique_ptr<Fluxmap> MacintoshEncoder::encode(
int physicalTrack, int physicalSide, const SectorSet& allSectors)
{
if ((physicalTrack < 0) || (physicalTrack >= MAC_TRACKS_PER_DISK))
return std::unique_ptr<Fluxmap>();
double clockRateUs = clockRateUsForTrack(physicalTrack) * clockCompensation;
int bitsPerRevolution = 200000.0 / clockRateUs;
std::vector<bool> bits(bitsPerRevolution);
unsigned cursor = 0;
fillBitmapTo(bits, cursor, postIndexGapUs / clockRateUs, { true, false });
lastBit = false;
unsigned numSectors = sectorsForTrack(physicalTrack);
for (int sectorId=0; sectorId<numSectors; sectorId++)
{
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
write_sector(bits, cursor, sectorData);
}
if (cursor >= bits.size())
Error() << fmt::format("track data overrun by {} bits", cursor - bits.size());
fillBitmapTo(bits, cursor, bits.size(), { true, false });
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
fluxmap->appendBits(bits, clockRateUs*1e3);
return fluxmap;
}

View File

@@ -1,11 +1,17 @@
#ifndef MACINTOSH_H
#define MACINTOSH_H
#include "decoders/decoders.h"
#include "encoders/encoders.h"
#define MAC_SECTOR_RECORD 0xd5aa96 /* 1101 0101 1010 1010 1001 0110 */
#define MAC_DATA_RECORD 0xd5aaad /* 1101 0101 1010 1010 1010 1101 */
#define MAC_SECTOR_LENGTH 524 /* yes, really */
#define MAC_ENCODED_SECTOR_LENGTH 703
#define MAC_FORMAT_BYTE 0x22
#define MAC_TRACKS_PER_DISK 80
class Sector;
class Fluxmap;
@@ -18,7 +24,21 @@ public:
RecordType advanceToNextRecord();
void decodeSectorRecord();
void decodeDataRecord();
std::set<unsigned> requiredSectors(Track& track) const;
};
class MacintoshEncoder : public AbstractEncoder
{
public:
virtual ~MacintoshEncoder() {}
public:
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
};
extern FlagGroup macintoshEncoderFlags;
#endif

View File

@@ -0,0 +1,61 @@
#include "globals.h"
#include "fluxmap.h"
#include "decoders/fluxmapreader.h"
#include "decoders/decoders.h"
#include "sector.h"
#include "micropolis.h"
#include "bytes.h"
#include "fmt/format.h"
/* The sector has a preamble of MFM 0x00s and uses 0xFF as a sync pattern. */
static const FluxPattern SECTOR_SYNC_PATTERN(32, 0xaaaa5555);
AbstractDecoder::RecordType MicropolisDecoder::advanceToNextRecord()
{
_fmr->seekToIndexMark();
const FluxMatcher* matcher = nullptr;
_sector->clock = _fmr->seekToPattern(SECTOR_SYNC_PATTERN, matcher);
if (matcher == &SECTOR_SYNC_PATTERN) {
readRawBits(16);
return SECTOR_RECORD;
}
return UNKNOWN_RECORD;
}
/* Adds all bytes, with carry. */
static uint8_t checksum(const Bytes& bytes) {
ByteReader br(bytes);
uint16_t sum = 0;
while (!br.eof()) {
if (sum > 0xFF) {
sum -= 0x100 - 1;
}
sum += br.read_8();
}
/* The last carry is ignored */
return sum & 0xFF;
}
void MicropolisDecoder::decodeSectorRecord()
{
auto rawbits = readRawBits(MICROPOLIS_ENCODED_SECTOR_SIZE*16);
auto bytes = decodeFmMfm(rawbits).slice(0, MICROPOLIS_ENCODED_SECTOR_SIZE);
ByteReader br(bytes);
br.read_8(); /* sync */
_sector->logicalTrack = br.read_8();
_sector->logicalSide = _sector->physicalSide;
_sector->logicalSector = br.read_8();
if (_sector->logicalSector > 15)
return;
if (_sector->logicalTrack > 77)
return;
br.read(10); /* OS data or padding */
_sector->data = br.read(256);
uint8_t wantChecksum = br.read_8();
uint8_t gotChecksum = checksum(bytes.slice(1, 2+266));
br.read(5); /* 4 byte ECC and ECC-present flag */
_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
}

View File

@@ -0,0 +1,18 @@
#ifndef ZILOGMCZ_H
#define ZILOGMCZ_H
#define MICROPOLIS_ENCODED_SECTOR_SIZE (1+2+266+6)
class Sector;
class Fluxmap;
class MicropolisDecoder : public AbstractDecoder
{
public:
virtual ~MicropolisDecoder() {}
RecordType advanceToNextRecord();
void decodeSectorRecord();
};
#endif

View File

@@ -37,7 +37,7 @@ AbstractDecoder::RecordType MxDecoder::advanceToNextRecord()
const FluxMatcher* matcher = nullptr;
_sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher);
readRawBits(32); /* skip the ID mark */
_logicalTrack = decodeFmMfm(readRawBits(32)).reader().read_be16();
_logicalTrack = decodeFmMfm(readRawBits(32)).slice(0, 32).reader().read_be16();
}
else if (_currentSector == 10)
{

87
arch/tids990/decoder.cc Normal file
View File

@@ -0,0 +1,87 @@
#include "globals.h"
#include "decoders/decoders.h"
#include "encoders/encoders.h"
#include "tids990/tids990.h"
#include "crc.h"
#include "fluxmap.h"
#include "decoders/fluxmapreader.h"
#include "sector.h"
#include "record.h"
#include "track.h"
#include <string.h>
#include <fmt/format.h>
/* The Texas Instruments DS990 uses MFM with a scheme similar to a simplified
* version of the IBM record scheme (it's actually easier to parse than IBM).
* There are 26 sectors per track, each holding a rather weird 288 bytes.
*/
/*
* Sector record:
* data: 0 1 0 1 0 1 0 1 .0 0 0 0 1 0 1 0 = 0x550a
* mfm: 00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 00 = 0x11112a44
* special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 00 = 0x11112244
* ^^
* When shifted out of phase, the special 0xa1 byte becomes an illegal
* encoding (you can't do 10 00). So this can't be spoofed by user data.
*/
const FluxPattern SECTOR_RECORD_PATTERN(32, 0x11112244);
/*
* Data record:
* data: 0 1 0 1 0 1 0 1 .0 0 0 0 1 0 1 1 = 0x550c
* mfm: 00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 01 = 0x11112a45
* special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 01 = 0x11112245
* ^^
* When shifted out of phase, the special 0xa1 byte becomes an illegal
* encoding (you can't do 10 00). So this can't be spoofed by user data.
*/
const FluxPattern DATA_RECORD_PATTERN(32, 0x11112245);
const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN });
AbstractDecoder::RecordType TiDs990Decoder::advanceToNextRecord()
{
const FluxMatcher* matcher = nullptr;
_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
if (matcher == &SECTOR_RECORD_PATTERN)
return RecordType::SECTOR_RECORD;
if (matcher == &DATA_RECORD_PATTERN)
return RecordType::DATA_RECORD;
return RecordType::UNKNOWN_RECORD;
}
void TiDs990Decoder::decodeSectorRecord()
{
auto bits = readRawBits(TIDS990_SECTOR_RECORD_SIZE*16);
auto bytes = decodeFmMfm(bits).slice(0, TIDS990_SECTOR_RECORD_SIZE);
ByteReader br(bytes);
uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_SECTOR_RECORD_SIZE-3));
br.seek(2);
_sector->logicalSide = br.read_8() >> 3;
_sector->logicalTrack = br.read_8();
br.read_8(); /* number of sectors per track */
_sector->logicalSector = br.read_8();
br.read_be16(); /* sector size */
uint16_t wantChecksum = br.read_be16();
if (wantChecksum == gotChecksum)
_sector->status = Sector::DATA_MISSING; /* correct but unintuitive */
}
void TiDs990Decoder::decodeDataRecord()
{
auto bits = readRawBits(TIDS990_DATA_RECORD_SIZE*16);
auto bytes = decodeFmMfm(bits).slice(0, TIDS990_DATA_RECORD_SIZE);
ByteReader br(bytes);
uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_DATA_RECORD_SIZE-3));
br.seek(2);
_sector->data = br.read(TIDS990_PAYLOAD_SIZE);
uint16_t wantChecksum = br.read_be16();
_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
}

176
arch/tids990/encoder.cc Normal file
View File

@@ -0,0 +1,176 @@
#include "globals.h"
#include "record.h"
#include "decoders/decoders.h"
#include "encoders/encoders.h"
#include "tids990.h"
#include "crc.h"
#include "sectorset.h"
#include "writer.h"
#include <fmt/format.h>
FlagGroup tids990EncoderFlags;
static IntFlag trackLengthMs(
{ "--tids990-track-length-ms" },
"Length of a track in milliseconds.",
166);
static IntFlag sectorCount(
{ "--tids990-sector-count" },
"Number of sectors per track.",
26);
static IntFlag clockRateKhz(
{ "--tids990-clock-rate-khz" },
"Clock rate of data to write.",
500);
static HexIntFlag am1Byte(
{ "--tids990-am1-byte" },
"16-bit RAW bit pattern to use for the AM1 ID byte",
0x2244);
static HexIntFlag am2Byte(
{ "--tids990-am2-byte" },
"16-bit RAW bit pattern to use for the AM2 ID byte",
0x2245);
static IntFlag gap1(
{ "--tids990-gap1-bytes" },
"Size of gap 1 (the post-index gap).",
80);
static IntFlag gap2(
{ "--tids990-gap2-bytes" },
"Size of gap 2 (the post-ID gap).",
21);
static IntFlag gap3(
{ "--tids990-gap3-bytes" },
"Size of gap 3 (the post-data or format gap).",
51);
static StringFlag sectorSkew(
{ "--tids990-sector-skew" },
"Order to emit sectors.",
"1mhc72nid83oje94pkfa50lgb6");
static int charToInt(char c)
{
if (isdigit(c))
return c - '0';
return 10 + tolower(c) - 'a';
}
void TiDs990Encoder::writeRawBits(uint32_t data, int width)
{
_cursor += width;
_lastBit = data & 1;
for (int i=0; i<width; i++)
{
unsigned pos = _cursor - i - 1;
if (pos < _bits.size())
_bits[pos] = data & 1;
data >>= 1;
}
}
void TiDs990Encoder::writeBytes(const Bytes& bytes)
{
encodeMfm(_bits, _cursor, bytes, _lastBit);
}
void TiDs990Encoder::writeBytes(int count, uint8_t byte)
{
Bytes bytes = { byte };
for (int i=0; i<count; i++)
writeBytes(bytes);
}
static uint8_t decodeUint16(uint16_t raw)
{
Bytes b;
ByteWriter bw(b);
bw.write_be16(raw);
return decodeFmMfm(b.toBits())[0];
}
std::unique_ptr<Fluxmap> TiDs990Encoder::encode(
int physicalTrack, int physicalSide, const SectorSet& allSectors)
{
double clockRateUs = 1e3 / clockRateKhz / 2.0;
int bitsPerRevolution = (trackLengthMs * 1000.0) / clockRateUs;
_bits.resize(bitsPerRevolution);
_cursor = 0;
uint8_t am1Unencoded = decodeUint16(am1Byte);
uint8_t am2Unencoded = decodeUint16(am2Byte);
writeBytes(gap1, 0x55);
bool first = true;
for (char sectorChar : sectorSkew.get())
{
int sectorId = charToInt(sectorChar);
if (!first)
writeBytes(gap3, 0x55);
first = false;
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
if (!sectorData)
Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId);
/* Writing the sector and data records are fantastically annoying.
* The CRC is calculated from the *very start* of the record, and
* include the malformed marker bytes. Our encoder doesn't know
* about this, of course, with the result that we have to construct
* the unencoded header, calculate the checksum, and then use the
* same logic to emit the bytes which require special encoding
* before encoding the rest of the header normally. */
{
Bytes header;
ByteWriter bw(header);
writeBytes(12, 0x55);
bw.write_8(am1Unencoded);
bw.write_8(sectorData->logicalSide << 3);
bw.write_8(sectorData->logicalTrack);
bw.write_8(sectorCount);
bw.write_8(sectorData->logicalSector);
bw.write_be16(sectorData->data.size());
uint16_t crc = crc16(CCITT_POLY, header);
bw.write_be16(crc);
writeRawBits(am1Byte, 16);
writeBytes(header.slice(1));
}
writeBytes(gap2, 0x55);
{
Bytes data;
ByteWriter bw(data);
writeBytes(12, 0x55);
bw.write_8(am2Unencoded);
bw += sectorData->data;
uint16_t crc = crc16(CCITT_POLY, data);
bw.write_be16(crc);
writeRawBits(am2Byte, 16);
writeBytes(data.slice(1));
}
}
if (_cursor >= _bits.size())
Error() << "track data overrun";
while (_cursor < _bits.size())
writeBytes(1, 0x55);
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
fluxmap->appendBits(_bits, clockRateUs*1e3);
return fluxmap;
}

47
arch/tids990/tids990.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef TIDS990_H
#define TIDS990_H
#define TIDS990_PAYLOAD_SIZE 288 /* bytes */
#define TIDS990_SECTOR_RECORD_SIZE 10 /* bytes */
#define TIDS990_DATA_RECORD_SIZE (TIDS990_PAYLOAD_SIZE + 4) /* bytes */
class Sector;
class SectorSet;
class Fluxmap;
class Track;
class TiDs990Decoder : public AbstractDecoder
{
public:
virtual ~TiDs990Decoder() {}
RecordType advanceToNextRecord();
void decodeSectorRecord();
void decodeDataRecord();
};
class TiDs990Encoder : public AbstractEncoder
{
public:
virtual ~TiDs990Encoder() {}
private:
void writeRawBits(uint32_t data, int width);
void writeBytes(const Bytes& bytes);
void writeBytes(int count, uint8_t value);
void writeSync();
public:
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
private:
std::vector<bool> _bits;
unsigned _cursor;
bool _lastBit;
};
extern FlagGroup tids990EncoderFlags;
#endif

2
dep/agg/AUTHORS Normal file
View File

@@ -0,0 +1,2 @@
Anti-Grain Geometry - Version 2.4
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)

63
dep/agg/README Normal file
View File

@@ -0,0 +1,63 @@
The Anti-Grain Geometry Project
A high quality rendering engine for C++
http://antigrain.com
Anti-Grain Geometry - Version 2.4
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
Permission to copy, use, modify, sell and distribute this software
is granted provided this copyright notice appears in all copies.
This software is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.
---------------------------------
Use automake to build the library.
If automake is not available you still can use the old make.
There is a very simple Makefile that can be used. Note that
if you use automake it will overwrite Makefile.
---------------------------------
If building on AmigaOS 4.0 or higher type the following for
instructions on what targets are available.
make -f Makefile.AmigaOS
To just build and install AGG into the standard AmigaOS SDK
ready for use type:
make -f Makefile.AmigaOS install
If you just want to build one demo (e.g. lion) use:
make -f Makefile.AmigaOS bin/lion
If you have any questions about the AmigaOS port please
contact Steven Solie (ssolie@telus.net) for help.
---------------------------------
To build all examples using SDL (Mac or Linux) just type:
cd /examples/sdl
make
Individual examples can be built with
make aa_test
In the same way the native Carbon examples can be built with
cd /examples/macosx_carbon
make
In both cases the static library will be built (if it was not already)
from the existing global Makefile in /src/.
The Makefiles for both SDL and Carbon will also attempt to download the
required .bmp files if they are not found in the system for a given
example. If the files could not be fetched (wget) the user will receive
a message explaining where to download the samples from (sphere.bmp,
etc.) Since all programs reside in the same directory there is no need
to duplicate the .bmp files for each program that needs to use them.
---------------------------------

7
dep/agg/README.md Normal file
View File

@@ -0,0 +1,7 @@
This is a vary stripped down copy of the Anti-Grain Antialiasing graphics
rendering library --- I've removed all the platform-specific and control stuff
so that it can be used to generate memory images only.
The original AGG site is dead, so this version is cloned from
https://github.com/NNemec/antigrain.

7
dep/agg/UPSTREAM.md Normal file
View File

@@ -0,0 +1,7 @@
This is a vary stripped down copy of the Anti-Grain Antialiasing graphics
rendering library --- I've removed all the platform-specific and control stuff
so that it can be used to generate memory images only.
The original AGG site is dead, so this version is cloned from
https://github.com/NNemec/antigrain.

View File

@@ -0,0 +1,49 @@
SUBDIRS = ctrl util platform
aggincludedir = $(includedir)/agg2
agginclude_HEADERS = \
agg_alpha_mask_u8.h agg_glyph_raster_bin.h agg_span_allocator.h \
agg_arc.h agg_gsv_text.h agg_span_converter.h \
agg_array.h agg_image_accessors.h agg_span_gouraud.h \
agg_arrowhead.h agg_image_filters.h agg_span_gouraud_gray.h \
agg_basics.h agg_line_aa_basics.h agg_span_gouraud_rgba.h \
agg_bezier_arc.h agg_math.h agg_span_gradient.h \
agg_bitset_iterator.h agg_blur.h agg_math_stroke.h \
agg_span_gradient_alpha.h agg_gradient_lut.h \
agg_bounding_rect.h agg_path_length.h agg_span_image_filter.h \
agg_bspline.h agg_path_storage.h agg_span_image_filter_gray.h \
agg_clip_liang_barsky.h agg_path_storage_integer.h agg_span_image_filter_rgb.h \
agg_color_gray.h agg_pattern_filters_rgba.h agg_span_image_filter_rgba.h \
agg_color_rgba.h agg_pixfmt_amask_adaptor.h agg_span_interpolator_adaptor.h \
agg_config.h agg_pixfmt_gray.h agg_span_interpolator_linear.h \
agg_conv_adaptor_vcgen.h agg_pixfmt_rgb.h agg_span_interpolator_persp.h \
agg_conv_adaptor_vpgen.h agg_pixfmt_rgb_packed.h agg_span_interpolator_trans.h \
agg_conv_bspline.h agg_pixfmt_rgba.h agg_pixfmt_transposer.h \
agg_span_pattern_gray.h \
agg_conv_clip_polygon.h agg_rasterizer_cells_aa.h agg_span_pattern_rgb.h \
agg_conv_clip_polyline.h agg_rasterizer_compound_aa.h agg_span_pattern_rgba.h \
agg_conv_close_polygon.h agg_rasterizer_outline.h agg_span_solid.h \
agg_conv_concat.h agg_rasterizer_outline_aa.h agg_span_subdiv_adaptor.h \
agg_conv_contour.h agg_rasterizer_scanline_aa.h agg_trans_affine.h \
agg_conv_curve.h agg_rasterizer_sl_clip.h agg_trans_bilinear.h \
agg_conv_dash.h agg_renderer_base.h agg_trans_double_path.h \
agg_conv_gpc.h agg_renderer_markers.h \
agg_conv_marker.h agg_renderer_mclip.h agg_trans_perspective.h \
agg_conv_marker_adaptor.h agg_renderer_outline_aa.h agg_trans_single_path.h \
agg_conv_segmentator.h agg_renderer_outline_image.h agg_trans_viewport.h \
agg_conv_shorten_path.h agg_renderer_primitives.h agg_trans_warp_magnifier.h \
agg_conv_smooth_poly1.h agg_renderer_raster_text.h agg_vcgen_bspline.h \
agg_conv_stroke.h agg_renderer_scanline.h agg_vcgen_contour.h \
agg_conv_transform.h agg_rendering_buffer.h agg_vcgen_dash.h \
agg_conv_unclose_polygon.h agg_rendering_buffer_dynarow.h agg_vcgen_markers_term.h \
agg_curves.h agg_rounded_rect.h agg_vcgen_smooth_poly1.h \
agg_scanline_bin.h agg_vcgen_stroke.h \
agg_dda_line.h agg_scanline_boolean_algebra.h agg_vcgen_vertex_sequence.h \
agg_ellipse.h agg_scanline_p.h agg_vertex_sequence.h \
agg_ellipse_bresenham.h agg_scanline_storage_aa.h agg_vpgen_clip_polygon.h \
agg_embedded_raster_fonts.h agg_scanline_storage_bin.h agg_vpgen_clip_polyline.h \
agg_font_cache_manager.h agg_scanline_u.h agg_vpgen_segmentator.h \
agg_gamma_functions.h agg_shorten_path.h \
agg_gamma_lut.h agg_simul_eq.h \
agg_font_cache_manager2.h agg_pixfmt_base.h agg_rasterizer_scanline_aa_nogamma.h \
agg_span_gradient_contour.h agg_span_gradient_image.h

568
dep/agg/include/agg2d.h Normal file
View File

@@ -0,0 +1,568 @@
//----------------------------------------------------------------------------
// Agg2D - Version 1.0
// Based on Anti-Grain Geometry
// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// 25 Jan 2007 - Ported to AGG 2.4 Jerry Evans (jerry@novadsp.com)
//
//----------------------------------------------------------------------------
#ifndef AGG2D_INCLUDED
#define AGG2D_INCLUDED
// With this define uncommented you can use floating-point pixel format
//#define AGG2D_USE_FLOAT_FORMAT
#include "agg_basics.h"
#include "agg_trans_affine.h"
#include "agg_trans_viewport.h"
#include "agg_path_storage.h"
#include "agg_conv_stroke.h"
#include "agg_conv_transform.h"
#include "agg_conv_curve.h"
#include "agg_rendering_buffer.h"
#include "agg_renderer_base.h"
#include "agg_renderer_scanline.h"
#include "agg_span_gradient.h"
#include "agg_span_image_filter_rgba.h"
#include "agg_span_allocator.h"
#include "agg_span_converter.h"
#include "agg_span_interpolator_linear.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_gamma_functions.h"
#include "agg_scanline_u.h"
#include "agg_bezier_arc.h"
#include "agg_rounded_rect.h"
#include "agg_font_cache_manager.h"
#include "agg_pixfmt_rgba.h"
#include "agg_image_accessors.h"
#include <string>
class Agg2D
{
#ifdef AGG2D_USE_FLOAT_FORMAT
typedef agg::rgba32 ColorType;
#else
typedef agg::rgba8 ColorType;
#endif
typedef agg::order_bgra ComponentOrder; // Platform dependent!
typedef agg::blender_rgba<ColorType, ComponentOrder> Blender;
typedef agg::comp_op_adaptor_rgba<ColorType, ComponentOrder> BlenderComp;
typedef agg::blender_rgba_pre<ColorType, ComponentOrder> BlenderPre;
typedef agg::comp_op_adaptor_rgba_pre<ColorType, ComponentOrder> BlenderCompPre;
typedef agg::pixfmt_alpha_blend_rgba<Blender, agg::rendering_buffer> PixFormat;
typedef agg::pixfmt_custom_blend_rgba<BlenderComp, agg::rendering_buffer> PixFormatComp;
typedef agg::pixfmt_alpha_blend_rgba<BlenderPre, agg::rendering_buffer> PixFormatPre;
typedef agg::pixfmt_custom_blend_rgba<BlenderCompPre, agg::rendering_buffer> PixFormatCompPre;
typedef agg::renderer_base<PixFormat> RendererBase;
typedef agg::renderer_base<PixFormatComp> RendererBaseComp;
typedef agg::renderer_base<PixFormatPre> RendererBasePre;
typedef agg::renderer_base<PixFormatCompPre> RendererBaseCompPre;
typedef agg::renderer_scanline_aa_solid<RendererBase> RendererSolid;
typedef agg::renderer_scanline_aa_solid<RendererBaseComp> RendererSolidComp;
typedef agg::span_allocator<ColorType> SpanAllocator;
typedef agg::pod_auto_array<ColorType, 256> GradientArray;
typedef agg::span_gradient<ColorType, agg::span_interpolator_linear<>, agg::gradient_x, GradientArray> LinearGradientSpan;
typedef agg::span_gradient<ColorType, agg::span_interpolator_linear<>, agg::gradient_circle, GradientArray> RadialGradientSpan;
typedef agg::conv_curve<agg::path_storage> ConvCurve;
typedef agg::conv_stroke<ConvCurve> ConvStroke;
typedef agg::conv_transform<ConvCurve> PathTransform;
typedef agg::conv_transform<ConvStroke> StrokeTransform;
enum Gradient
{
Solid,
Linear,
Radial
};
public:
friend class Agg2DRenderer;
// Use srgba8 as the "user" color type, even though the underlying color type
// might be something else, such as rgba32. This allows code based on
// 8-bit sRGB values to carry on working as before.
typedef agg::srgba8 Color;
typedef agg::rect_i Rect;
typedef agg::rect_d RectD;
typedef agg::trans_affine Affine;
enum LineJoin
{
JoinMiter = agg::miter_join,
JoinRound = agg::round_join,
JoinBevel = agg::bevel_join
};
enum LineCap
{
CapButt = agg::butt_cap,
CapSquare = agg::square_cap,
CapRound = agg::round_cap
};
enum TextAlignment
{
AlignLeft,
AlignRight,
AlignCenter,
};
enum DrawPathFlag
{
FillOnly,
StrokeOnly,
FillAndStroke,
FillWithLineColor
};
enum ViewportOption
{
Anisotropic,
XMinYMin,
XMidYMin,
XMaxYMin,
XMinYMid,
XMidYMid,
XMaxYMid,
XMinYMax,
XMidYMax,
XMaxYMax
};
struct Transformations
{
double affineMatrix[6];
};
struct Image
{
agg::rendering_buffer renBuf;
Image() {}
Image(unsigned char* buf, unsigned width, unsigned height, int stride) :
renBuf(buf, width, height, stride) {}
void attach(unsigned char* buf, unsigned width, unsigned height, int stride)
{
renBuf.attach(buf, width, height, stride);
}
int width() const { return renBuf.width(); }
int height() const { return renBuf.height(); }
void premultiply();
void demultiply();
};
enum ImageFilter
{
NoFilter,
Bilinear,
Hanning,
Hermite,
Quadric,
Bicubic,
Catrom,
Spline16,
Spline36,
Blackman144
};
enum ImageResample
{
NoResample,
ResampleAlways,
ResampleOnZoomOut
};
enum FontCacheType
{
RasterFontCache,
VectorFontCache
};
enum BlendMode
{
BlendAlpha = agg::end_of_comp_op_e,
BlendClear = agg::comp_op_clear,
BlendSrc = agg::comp_op_src,
BlendDst = agg::comp_op_dst,
BlendSrcOver = agg::comp_op_src_over,
BlendDstOver = agg::comp_op_dst_over,
BlendSrcIn = agg::comp_op_src_in,
BlendDstIn = agg::comp_op_dst_in,
BlendSrcOut = agg::comp_op_src_out,
BlendDstOut = agg::comp_op_dst_out,
BlendSrcAtop = agg::comp_op_src_atop,
BlendDstAtop = agg::comp_op_dst_atop,
BlendXor = agg::comp_op_xor,
BlendAdd = agg::comp_op_plus,
BlendMultiply = agg::comp_op_multiply,
BlendScreen = agg::comp_op_screen,
BlendOverlay = agg::comp_op_overlay,
BlendDarken = agg::comp_op_darken,
BlendLighten = agg::comp_op_lighten,
BlendColorDodge = agg::comp_op_color_dodge,
BlendColorBurn = agg::comp_op_color_burn,
BlendHardLight = agg::comp_op_hard_light,
BlendSoftLight = agg::comp_op_soft_light,
BlendDifference = agg::comp_op_difference,
BlendExclusion = agg::comp_op_exclusion,
};
enum Direction
{
CW, CCW
};
~Agg2D();
Agg2D();
// Setup
//-----------------------
void attach(unsigned char* buf, unsigned width, unsigned height, int stride);
void attach(Image& img);
void clipBox(double x1, double y1, double x2, double y2);
RectD clipBox() const;
void clearAll(Color c);
void clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255);
void clearClipBox(Color c);
void clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255);
// Conversions
//-----------------------
void worldToScreen(double& x, double& y) const;
void screenToWorld(double& x, double& y) const;
double worldToScreen(double scalar) const;
double screenToWorld(double scalar) const;
void alignPoint(double& x, double& y) const;
bool inBox(double worldX, double worldY) const;
// General Attributes
//-----------------------
void blendMode(BlendMode m);
BlendMode blendMode() const;
void imageBlendMode(BlendMode m);
BlendMode imageBlendMode() const;
void imageBlendColor(Color c);
void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
Color imageBlendColor() const;
void masterAlpha(double a);
double masterAlpha() const;
void antiAliasGamma(double g);
double antiAliasGamma() const;
void fillColor(Color c);
void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
void noFill();
void lineColor(Color c);
void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
void noLine();
Color fillColor() const;
Color lineColor() const;
void fillLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0);
void lineLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0);
void fillRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0);
void lineRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0);
void fillRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3);
void lineRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3);
void fillRadialGradient(double x, double y, double r);
void lineRadialGradient(double x, double y, double r);
void lineWidth(double w);
double lineWidth(double w) const;
void lineCap(LineCap cap);
LineCap lineCap() const;
void lineJoin(LineJoin join);
LineJoin lineJoin() const;
void fillEvenOdd(bool evenOddFlag);
bool fillEvenOdd() const;
void textAlignment(TextAlignment alignment);
void textSize(double sizeX, double sizeY);
inline void textSize(double size) { textSize(size, size); }
// Transformations
//-----------------------
Transformations transformations() const;
void transformations(const Transformations& tr);
void resetTransformations();
void affine(const Affine& tr);
void affine(const Transformations& tr);
void rotate(double angle);
void scale(double sx, double sy);
void skew(double sx, double sy);
void translate(double x, double y);
void parallelogram(double x1, double y1, double x2, double y2, const double* para);
void viewport(double worldX1, double worldY1, double worldX2, double worldY2,
double screenX1, double screenY1, double screenX2, double screenY2,
ViewportOption opt=XMidYMid);
// Basic Shapes
//-----------------------
void line(double x1, double y1, double x2, double y2);
void triangle(double x1, double y1, double x2, double y2, double x3, double y3);
void rectangle(double x1, double y1, double x2, double y2);
void roundedRect(double x1, double y1, double x2, double y2, double r);
void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry);
void roundedRect(double x1, double y1, double x2, double y2,
double rxBottom, double ryBottom,
double rxTop, double ryTop);
void ellipse(double cx, double cy, double rx, double ry);
void arc(double cx, double cy, double rx, double ry, double start, double sweep);
void star(double cx, double cy, double r1, double r2, double startAngle, int numRays);
void curve(double x1, double y1, double x2, double y2, double x3, double y3);
void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
void polygon(double* xy, int numPoints);
void polyline(double* xy, int numPoints);
// Path commands
//-----------------------
void resetPath();
void moveTo(double x, double y);
void moveRel(double dx, double dy);
void lineTo(double x, double y);
void lineRel(double dx, double dy);
void horLineTo(double x);
void horLineRel(double dx);
void verLineTo(double y);
void verLineRel(double dy);
void arcTo(double rx, double ry,
double angle,
bool largeArcFlag,
bool sweepFlag,
double x, double y);
void arcRel(double rx, double ry,
double angle,
bool largeArcFlag,
bool sweepFlag,
double dx, double dy);
void quadricCurveTo(double xCtrl, double yCtrl,
double xTo, double yTo);
void quadricCurveRel(double dxCtrl, double dyCtrl,
double dxTo, double dyTo);
void quadricCurveTo(double xTo, double yTo);
void quadricCurveRel(double dxTo, double dyTo);
void cubicCurveTo(double xCtrl1, double yCtrl1,
double xCtrl2, double yCtrl2,
double xTo, double yTo);
void cubicCurveRel(double dxCtrl1, double dyCtrl1,
double dxCtrl2, double dyCtrl2,
double dxTo, double dyTo);
void cubicCurveTo(double xCtrl2, double yCtrl2,
double xTo, double yTo);
void cubicCurveRel(double xCtrl2, double yCtrl2,
double xTo, double yTo);
void addEllipse(double cx, double cy, double rx, double ry, Direction dir);
void text(double x, double y, const std::string& text);
void closePolygon();
void drawPath(DrawPathFlag flag = FillAndStroke);
void drawPathNoTransform(DrawPathFlag flag = FillAndStroke);
// Image Transformations
//-----------------------
void imageFilter(ImageFilter f);
ImageFilter imageFilter() const;
void imageResample(ImageResample f);
ImageResample imageResample() const;
void transformImage(const Image& img,
int imgX1, int imgY1, int imgX2, int imgY2,
double dstX1, double dstY1, double dstX2, double dstY2);
void transformImage(const Image& img,
double dstX1, double dstY1, double dstX2, double dstY2);
void transformImage(const Image& img,
int imgX1, int imgY1, int imgX2, int imgY2,
const double* parallelogram);
void transformImage(const Image& img, const double* parallelogram);
void transformImagePath(const Image& img,
int imgX1, int imgY1, int imgX2, int imgY2,
double dstX1, double dstY1, double dstX2, double dstY2);
void transformImagePath(const Image& img,
double dstX1, double dstY1, double dstX2, double dstY2);
void transformImagePath(const Image& img,
int imgX1, int imgY1, int imgX2, int imgY2,
const double* parallelogram);
void transformImagePath(const Image& img, const double* parallelogram);
// Image Blending (no transformations available)
void blendImage(Image& img,
int imgX1, int imgY1, int imgX2, int imgY2,
double dstX, double dstY, unsigned alpha=255);
void blendImage(Image& img, double dstX, double dstY, unsigned alpha=255);
// Copy image directly, together with alpha-channel
void copyImage(Image& img,
int imgX1, int imgY1, int imgX2, int imgY2,
double dstX, double dstY);
void copyImage(Image& img, double dstX, double dstY);
// Auxiliary
//-----------------------
static double pi() { return agg::pi; }
static double deg2Rad(double v) { return v * agg::pi / 180.0; }
static double rad2Deg(double v) { return v * 180.0 / agg::pi; }
private:
void render(bool fillColor);
#ifdef AGG_USE_FONTS
void render(FontRasterizer& ras, FontScanline& sl);
#endif // AGG_USE_FONTS
void addLine(double x1, double y1, double x2, double y2);
void updateRasterizerGamma();
void renderImage(const Image& img, int x1, int y1, int x2, int y2, const double* parl);
agg::rendering_buffer m_rbuf;
PixFormat m_pixFormat;
PixFormatComp m_pixFormatComp;
PixFormatPre m_pixFormatPre;
PixFormatCompPre m_pixFormatCompPre;
RendererBase m_renBase;
RendererBaseComp m_renBaseComp;
RendererBasePre m_renBasePre;
RendererBaseCompPre m_renBaseCompPre;
RendererSolid m_renSolid;
RendererSolidComp m_renSolidComp;
SpanAllocator m_allocator;
RectD m_clipBox;
BlendMode m_blendMode;
BlendMode m_imageBlendMode;
Color m_imageBlendColor;
agg::scanline_u8 m_scanline;
agg::rasterizer_scanline_aa<> m_rasterizer;
double m_masterAlpha;
double m_antiAliasGamma;
Color m_fillColor;
Color m_lineColor;
GradientArray m_fillGradient;
GradientArray m_lineGradient;
LineCap m_lineCap;
LineJoin m_lineJoin;
Gradient m_fillGradientFlag;
Gradient m_lineGradientFlag;
agg::trans_affine m_fillGradientMatrix;
agg::trans_affine m_lineGradientMatrix;
double m_fillGradientD1;
double m_lineGradientD1;
double m_fillGradientD2;
double m_lineGradientD2;
TextAlignment m_textAlignment;
double m_textSizeX;
double m_textSizeY;
ImageFilter m_imageFilter;
ImageResample m_imageResample;
agg::image_filter_lut m_imageFilterLut;
agg::span_interpolator_linear<> m_fillGradientInterpolator;
agg::span_interpolator_linear<> m_lineGradientInterpolator;
agg::gradient_x m_linearGradientFunction;
agg::gradient_circle m_radialGradientFunction;
double m_lineWidth;
bool m_evenOddFlag;
agg::path_storage m_path;
agg::trans_affine m_transform;
ConvCurve m_convCurve;
ConvStroke m_convStroke;
PathTransform m_pathTransform;
StrokeTransform m_strokeTransform;
#ifdef AGG_USE_FONTS
#ifndef AGG2D_USE_FREETYPE
HDC m_fontDC;
#endif
FontEngine m_fontEngine;
FontCacheManager m_fontCacheManager;
#endif
};
inline bool operator == (const Agg2D::Color& c1, const Agg2D::Color& c2)
{
return c1.r == c2.r && c1.g == c2.g && c1.b == c2.b && c1.a == c2.a;
}
inline bool operator != (const Agg2D::Color& c1, const Agg2D::Color& c2)
{
return !(c1 == c2);
}
#endif

View File

@@ -0,0 +1,499 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// scanline_u8 class
//
//----------------------------------------------------------------------------
#ifndef AGG_ALPHA_MASK_U8_INCLUDED
#define AGG_ALPHA_MASK_U8_INCLUDED
#include <cstring>
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//===================================================one_component_mask_u8
struct one_component_mask_u8
{
static unsigned calculate(const int8u* p) { return *p; }
};
//=====================================================rgb_to_gray_mask_u8
template<unsigned R, unsigned G, unsigned B>
struct rgb_to_gray_mask_u8
{
static unsigned calculate(const int8u* p)
{
return (p[R]*77 + p[G]*150 + p[B]*29) >> 8;
}
};
//==========================================================alpha_mask_u8
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
class alpha_mask_u8
{
public:
typedef int8u cover_type;
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
enum cover_scale_e
{
cover_shift = 8,
cover_none = 0,
cover_full = 255
};
alpha_mask_u8() : m_rbuf(0) {}
explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
MaskF& mask_function() { return m_mask_function; }
const MaskF& mask_function() const { return m_mask_function; }
//--------------------------------------------------------------------
cover_type pixel(int x, int y) const
{
if(x >= 0 && y >= 0 &&
x < (int)m_rbuf->width() &&
y < (int)m_rbuf->height())
{
return (cover_type)m_mask_function.calculate(
m_rbuf->row_ptr(y) + x * Step + Offset);
}
return 0;
}
//--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
{
if(x >= 0 && y >= 0 &&
x < (int)m_rbuf->width() &&
y < (int)m_rbuf->height())
{
return (cover_type)((cover_full + val *
m_mask_function.calculate(
m_rbuf->row_ptr(y) + x * Step + Offset)) >>
cover_shift);
}
return 0;
}
//--------------------------------------------------------------------
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(y < 0 || y > ymax)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if(x < 0)
{
count += x;
if(count <= 0)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
std::memset(covers, 0, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
if(x + count > xmax)
{
int rest = x + count - xmax - 1;
count -= rest;
if(count <= 0)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
std::memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*covers++ = (cover_type)m_mask_function.calculate(mask);
mask += Step;
}
while(--count);
}
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(y < 0 || y > ymax)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if(x < 0)
{
count += x;
if(count <= 0)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
std::memset(covers, 0, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
if(x + count > xmax)
{
int rest = x + count - xmax - 1;
count -= rest;
if(count <= 0)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
std::memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*covers = (cover_type)((cover_full + (*covers) *
m_mask_function.calculate(mask)) >>
cover_shift);
++covers;
mask += Step;
}
while(--count);
}
//--------------------------------------------------------------------
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(x < 0 || x > xmax)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if(y < 0)
{
count += y;
if(count <= 0)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
std::memset(covers, 0, -y * sizeof(cover_type));
covers -= y;
y = 0;
}
if(y + count > ymax)
{
int rest = y + count - ymax - 1;
count -= rest;
if(count <= 0)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
std::memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*covers++ = (cover_type)m_mask_function.calculate(mask);
mask += m_rbuf->stride();
}
while(--count);
}
//--------------------------------------------------------------------
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(x < 0 || x > xmax)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if(y < 0)
{
count += y;
if(count <= 0)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
std::memset(covers, 0, -y * sizeof(cover_type));
covers -= y;
y = 0;
}
if(y + count > ymax)
{
int rest = y + count - ymax - 1;
count -= rest;
if(count <= 0)
{
std::memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
std::memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*covers = (cover_type)((cover_full + (*covers) *
m_mask_function.calculate(mask)) >>
cover_shift);
++covers;
mask += m_rbuf->stride();
}
while(--count);
}
private:
alpha_mask_u8(const self_type&);
const self_type& operator = (const self_type&);
rendering_buffer* m_rbuf;
MaskF m_mask_function;
};
typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8
typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r
typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g
typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b
typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r
typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g
typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b
typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
//==========================================================amask_no_clip_u8
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
class amask_no_clip_u8
{
public:
typedef int8u cover_type;
typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
enum cover_scale_e
{
cover_shift = 8,
cover_none = 0,
cover_full = 255
};
amask_no_clip_u8() : m_rbuf(0) {}
explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
MaskF& mask_function() { return m_mask_function; }
const MaskF& mask_function() const { return m_mask_function; }
//--------------------------------------------------------------------
cover_type pixel(int x, int y) const
{
return (cover_type)m_mask_function.calculate(
m_rbuf->row_ptr(y) + x * Step + Offset);
}
//--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
{
return (cover_type)((cover_full + val *
m_mask_function.calculate(
m_rbuf->row_ptr(y) + x * Step + Offset)) >>
cover_shift);
}
//--------------------------------------------------------------------
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
{
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*dst++ = (cover_type)m_mask_function.calculate(mask);
mask += Step;
}
while(--num_pix);
}
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*dst = (cover_type)((cover_full + (*dst) *
m_mask_function.calculate(mask)) >>
cover_shift);
++dst;
mask += Step;
}
while(--num_pix);
}
//--------------------------------------------------------------------
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
{
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*dst++ = (cover_type)m_mask_function.calculate(mask);
mask += m_rbuf->stride();
}
while(--num_pix);
}
//--------------------------------------------------------------------
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
{
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*dst = (cover_type)((cover_full + (*dst) *
m_mask_function.calculate(mask)) >>
cover_shift);
++dst;
mask += m_rbuf->stride();
}
while(--num_pix);
}
private:
amask_no_clip_u8(const self_type&);
const self_type& operator = (const self_type&);
rendering_buffer* m_rbuf;
MaskF m_mask_function;
};
typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r
typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g
typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b
typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r
typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g
typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b
typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
}
#endif

73
dep/agg/include/agg_arc.h Normal file
View File

@@ -0,0 +1,73 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Arc vertex generator
//
//----------------------------------------------------------------------------
#ifndef AGG_ARC_INCLUDED
#define AGG_ARC_INCLUDED
#include "agg_basics.h"
namespace agg
{
//=====================================================================arc
//
// See Implementation agg_arc.cpp
//
class arc
{
public:
arc() : m_scale(1.0), m_initialized(false) {}
arc(double x, double y,
double rx, double ry,
double a1, double a2,
bool ccw=true);
void init(double x, double y,
double rx, double ry,
double a1, double a2,
bool ccw=true);
void approximation_scale(double s);
double approximation_scale() const { return m_scale; }
void rewind(unsigned);
unsigned vertex(double* x, double* y);
private:
void normalize(double a1, double a2, bool ccw);
double m_x;
double m_y;
double m_rx;
double m_ry;
double m_angle;
double m_start;
double m_end;
double m_scale;
double m_da;
bool m_ccw;
bool m_initialized;
unsigned m_path_cmd;
};
}
#endif

1119
dep/agg/include/agg_array.h Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Simple arrowhead/arrowtail generator
//
//----------------------------------------------------------------------------
#ifndef AGG_ARROWHEAD_INCLUDED
#define AGG_ARROWHEAD_INCLUDED
#include "agg_basics.h"
namespace agg
{
//===============================================================arrowhead
//
// See implementation agg_arrowhead.cpp
//
class arrowhead
{
public:
arrowhead();
void head(double d1, double d2, double d3, double d4)
{
m_head_d1 = d1;
m_head_d2 = d2;
m_head_d3 = d3;
m_head_d4 = d4;
m_head_flag = true;
}
void head() { m_head_flag = true; }
void no_head() { m_head_flag = false; }
void tail(double d1, double d2, double d3, double d4)
{
m_tail_d1 = d1;
m_tail_d2 = d2;
m_tail_d3 = d3;
m_tail_d4 = d4;
m_tail_flag = true;
}
void tail() { m_tail_flag = true; }
void no_tail() { m_tail_flag = false; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
double m_head_d1;
double m_head_d2;
double m_head_d3;
double m_head_d4;
double m_tail_d1;
double m_tail_d2;
double m_tail_d3;
double m_tail_d4;
bool m_head_flag;
bool m_tail_flag;
double m_coord[16];
unsigned m_cmd[8];
unsigned m_curr_id;
unsigned m_curr_coord;
};
}
#endif

View File

@@ -0,0 +1,574 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_BASICS_INCLUDED
#define AGG_BASICS_INCLUDED
#include <cmath>
#include "agg_config.h"
//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
#ifdef AGG_CUSTOM_ALLOCATOR
#include "agg_allocator.h"
#else
namespace agg
{
// The policy of all AGG containers and memory allocation strategy
// in general is that no allocated data requires explicit construction.
// It means that the allocator can be really simple; you can even
// replace new/delete to malloc/free. The constructors and destructors
// won't be called in this case, however everything will remain working.
// The second argument of deallocate() is the size of the allocated
// block. You can use this information if you wish.
//------------------------------------------------------------pod_allocator
template<class T> struct pod_allocator
{
static T* allocate(unsigned num) { return new T [num]; }
static void deallocate(T* ptr, unsigned) { delete [] ptr; }
};
// Single object allocator. It's also can be replaced with your custom
// allocator. The difference is that it can only allocate a single
// object and the constructor and destructor must be called.
// In AGG there is no need to allocate an array of objects with
// calling their constructors (only single ones). So that, if you
// replace these new/delete to malloc/free make sure that the in-place
// new is called and take care of calling the destructor too.
//------------------------------------------------------------obj_allocator
template<class T> struct obj_allocator
{
static T* allocate() { return new T; }
static void deallocate(T* ptr) { delete ptr; }
};
}
#endif
//-------------------------------------------------------- Default basic types
//
// If the compiler has different capacity of the basic types you can redefine
// them via the compiler command line or by generating agg_config.h that is
// empty by default.
//
#ifndef AGG_INT8
#define AGG_INT8 signed char
#endif
#ifndef AGG_INT8U
#define AGG_INT8U unsigned char
#endif
#ifndef AGG_INT16
#define AGG_INT16 short
#endif
#ifndef AGG_INT16U
#define AGG_INT16U unsigned short
#endif
#ifndef AGG_INT32
#define AGG_INT32 int
#endif
#ifndef AGG_INT32U
#define AGG_INT32U unsigned
#endif
#ifndef AGG_INT64
#if defined(_MSC_VER) || defined(__BORLANDC__)
#define AGG_INT64 signed __int64
#else
#define AGG_INT64 signed long long
#endif
#endif
#ifndef AGG_INT64U
#if defined(_MSC_VER) || defined(__BORLANDC__)
#define AGG_INT64U unsigned __int64
#else
#define AGG_INT64U unsigned long long
#endif
#endif
//------------------------------------------------ Some fixes for MS Visual C++
#if defined(_MSC_VER)
#pragma warning(disable:4786) // Identifier was truncated...
#endif
#if defined(_MSC_VER)
#define AGG_INLINE __forceinline
#else
#define AGG_INLINE inline
#endif
namespace agg
{
//-------------------------------------------------------------------------
typedef AGG_INT8 int8; //----int8
typedef AGG_INT8U int8u; //----int8u
typedef AGG_INT16 int16; //----int16
typedef AGG_INT16U int16u; //----int16u
typedef AGG_INT32 int32; //----int32
typedef AGG_INT32U int32u; //----int32u
typedef AGG_INT64 int64; //----int64
typedef AGG_INT64U int64u; //----int64u
#if defined(AGG_FISTP)
#pragma warning(push)
#pragma warning(disable : 4035) //Disable warning "no return value"
AGG_INLINE int iround(double v) //-------iround
{
int t;
__asm fld qword ptr [v]
__asm fistp dword ptr [t]
__asm mov eax, dword ptr [t]
}
AGG_INLINE unsigned uround(double v) //-------uround
{
unsigned t;
__asm fld qword ptr [v]
__asm fistp dword ptr [t]
__asm mov eax, dword ptr [t]
}
#pragma warning(pop)
AGG_INLINE int ifloor(double v)
{
return int(floor(v));
}
AGG_INLINE unsigned ufloor(double v) //-------ufloor
{
return unsigned(floor(v));
}
AGG_INLINE int iceil(double v)
{
return int(ceil(v));
}
AGG_INLINE unsigned uceil(double v) //--------uceil
{
return unsigned(ceil(v));
}
#elif defined(AGG_QIFIST)
AGG_INLINE int iround(double v)
{
return int(v);
}
AGG_INLINE int uround(double v)
{
return unsigned(v);
}
AGG_INLINE int ifloor(double v)
{
return int(std::floor(v));
}
AGG_INLINE unsigned ufloor(double v)
{
return unsigned(std::floor(v));
}
AGG_INLINE int iceil(double v)
{
return int(std::ceil(v));
}
AGG_INLINE unsigned uceil(double v)
{
return unsigned(std::ceil(v));
}
#else
AGG_INLINE int iround(double v)
{
return int((v < 0.0) ? v - 0.5 : v + 0.5);
}
AGG_INLINE int uround(double v)
{
return unsigned(v + 0.5);
}
AGG_INLINE int ifloor(double v)
{
int i = int(v);
return i - (i > v);
}
AGG_INLINE unsigned ufloor(double v)
{
return unsigned(v);
}
AGG_INLINE int iceil(double v)
{
return int(std::ceil(v));
}
AGG_INLINE unsigned uceil(double v)
{
return unsigned(std::ceil(v));
}
#endif
//---------------------------------------------------------------saturation
template<int Limit> struct saturation
{
AGG_INLINE static int iround(double v)
{
if(v < double(-Limit)) return -Limit;
if(v > double( Limit)) return Limit;
return agg::iround(v);
}
};
//------------------------------------------------------------------mul_one
template<unsigned Shift> struct mul_one
{
AGG_INLINE static unsigned mul(unsigned a, unsigned b)
{
unsigned q = a * b + (1 << (Shift-1));
return (q + (q >> Shift)) >> Shift;
}
};
//-------------------------------------------------------------------------
typedef unsigned char cover_type; //----cover_type
enum cover_scale_e
{
cover_shift = 8, //----cover_shift
cover_size = 1 << cover_shift, //----cover_size
cover_mask = cover_size - 1, //----cover_mask
cover_none = 0, //----cover_none
cover_full = cover_mask //----cover_full
};
//----------------------------------------------------poly_subpixel_scale_e
// These constants determine the subpixel accuracy, to be more precise,
// the number of bits of the fractional part of the coordinates.
// The possible coordinate capacity in bits can be calculated by formula:
// sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
// 8-bits fractional part the capacity is 24 bits.
enum poly_subpixel_scale_e
{
poly_subpixel_shift = 8, //----poly_subpixel_shift
poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale
poly_subpixel_mask = poly_subpixel_scale-1 //----poly_subpixel_mask
};
//----------------------------------------------------------filling_rule_e
enum filling_rule_e
{
fill_non_zero,
fill_even_odd
};
//-----------------------------------------------------------------------pi
const double pi = 3.14159265358979323846;
//------------------------------------------------------------------deg2rad
inline double deg2rad(double deg)
{
return deg * pi / 180.0;
}
//------------------------------------------------------------------rad2deg
inline double rad2deg(double rad)
{
return rad * 180.0 / pi;
}
//----------------------------------------------------------------rect_base
template<class T> struct rect_base
{
typedef T value_type;
typedef rect_base<T> self_type;
T x1, y1, x2, y2;
rect_base() {}
rect_base(T x1_, T y1_, T x2_, T y2_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
void init(T x1_, T y1_, T x2_, T y2_)
{
x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
}
const self_type& normalize()
{
T t;
if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
return *this;
}
bool clip(const self_type& r)
{
if(x2 > r.x2) x2 = r.x2;
if(y2 > r.y2) y2 = r.y2;
if(x1 < r.x1) x1 = r.x1;
if(y1 < r.y1) y1 = r.y1;
return x1 <= x2 && y1 <= y2;
}
bool is_valid() const
{
return x1 <= x2 && y1 <= y2;
}
bool hit_test(T x, T y) const
{
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
}
bool overlaps(const self_type& r) const
{
return !(r.x1 > x2 || r.x2 < x1
|| r.y1 > y2 || r.y2 < y1);
}
};
//-----------------------------------------------------intersect_rectangles
template<class Rect>
inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
{
Rect r = r1;
// First process x2,y2 because the other order
// results in Internal Compiler Error under
// Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
// case of "Maximize Speed" optimization option.
//-----------------
if(r.x2 > r2.x2) r.x2 = r2.x2;
if(r.y2 > r2.y2) r.y2 = r2.y2;
if(r.x1 < r2.x1) r.x1 = r2.x1;
if(r.y1 < r2.y1) r.y1 = r2.y1;
return r;
}
//---------------------------------------------------------unite_rectangles
template<class Rect>
inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
{
Rect r = r1;
if(r.x2 < r2.x2) r.x2 = r2.x2;
if(r.y2 < r2.y2) r.y2 = r2.y2;
if(r.x1 > r2.x1) r.x1 = r2.x1;
if(r.y1 > r2.y1) r.y1 = r2.y1;
return r;
}
typedef rect_base<int> rect_i; //----rect_i
typedef rect_base<float> rect_f; //----rect_f
typedef rect_base<double> rect_d; //----rect_d
//---------------------------------------------------------path_commands_e
enum path_commands_e
{
path_cmd_stop = 0, //----path_cmd_stop
path_cmd_move_to = 1, //----path_cmd_move_to
path_cmd_line_to = 2, //----path_cmd_line_to
path_cmd_curve3 = 3, //----path_cmd_curve3
path_cmd_curve4 = 4, //----path_cmd_curve4
path_cmd_curveN = 5, //----path_cmd_curveN
path_cmd_catrom = 6, //----path_cmd_catrom
path_cmd_ubspline = 7, //----path_cmd_ubspline
path_cmd_end_poly = 0x0F, //----path_cmd_end_poly
path_cmd_mask = 0x0F //----path_cmd_mask
};
//------------------------------------------------------------path_flags_e
enum path_flags_e
{
path_flags_none = 0, //----path_flags_none
path_flags_ccw = 0x10, //----path_flags_ccw
path_flags_cw = 0x20, //----path_flags_cw
path_flags_close = 0x40, //----path_flags_close
path_flags_mask = 0xF0 //----path_flags_mask
};
//---------------------------------------------------------------is_vertex
inline bool is_vertex(unsigned c)
{
return c >= path_cmd_move_to && c < path_cmd_end_poly;
}
//--------------------------------------------------------------is_drawing
inline bool is_drawing(unsigned c)
{
return c >= path_cmd_line_to && c < path_cmd_end_poly;
}
//-----------------------------------------------------------------is_stop
inline bool is_stop(unsigned c)
{
return c == path_cmd_stop;
}
//--------------------------------------------------------------is_move_to
inline bool is_move_to(unsigned c)
{
return c == path_cmd_move_to;
}
//--------------------------------------------------------------is_line_to
inline bool is_line_to(unsigned c)
{
return c == path_cmd_line_to;
}
//----------------------------------------------------------------is_curve
inline bool is_curve(unsigned c)
{
return c == path_cmd_curve3 || c == path_cmd_curve4;
}
//---------------------------------------------------------------is_curve3
inline bool is_curve3(unsigned c)
{
return c == path_cmd_curve3;
}
//---------------------------------------------------------------is_curve4
inline bool is_curve4(unsigned c)
{
return c == path_cmd_curve4;
}
//-------------------------------------------------------------is_end_poly
inline bool is_end_poly(unsigned c)
{
return (c & path_cmd_mask) == path_cmd_end_poly;
}
//----------------------------------------------------------------is_close
inline bool is_close(unsigned c)
{
return (c & ~(path_flags_cw | path_flags_ccw)) ==
(path_cmd_end_poly | path_flags_close);
}
//------------------------------------------------------------is_next_poly
inline bool is_next_poly(unsigned c)
{
return is_stop(c) || is_move_to(c) || is_end_poly(c);
}
//-------------------------------------------------------------------is_cw
inline bool is_cw(unsigned c)
{
return (c & path_flags_cw) != 0;
}
//------------------------------------------------------------------is_ccw
inline bool is_ccw(unsigned c)
{
return (c & path_flags_ccw) != 0;
}
//-------------------------------------------------------------is_oriented
inline bool is_oriented(unsigned c)
{
return (c & (path_flags_cw | path_flags_ccw)) != 0;
}
//---------------------------------------------------------------is_closed
inline bool is_closed(unsigned c)
{
return (c & path_flags_close) != 0;
}
//----------------------------------------------------------get_close_flag
inline unsigned get_close_flag(unsigned c)
{
return c & path_flags_close;
}
//-------------------------------------------------------clear_orientation
inline unsigned clear_orientation(unsigned c)
{
return c & ~(path_flags_cw | path_flags_ccw);
}
//---------------------------------------------------------get_orientation
inline unsigned get_orientation(unsigned c)
{
return c & (path_flags_cw | path_flags_ccw);
}
//---------------------------------------------------------set_orientation
inline unsigned set_orientation(unsigned c, unsigned o)
{
return clear_orientation(c) | o;
}
//--------------------------------------------------------------point_base
template<class T> struct point_base
{
typedef T value_type;
T x,y;
point_base() {}
point_base(T x_, T y_) : x(x_), y(y_) {}
};
typedef point_base<int> point_i; //-----point_i
typedef point_base<float> point_f; //-----point_f
typedef point_base<double> point_d; //-----point_d
//-------------------------------------------------------------vertex_base
template<class T> struct vertex_base
{
typedef T value_type;
T x,y;
unsigned cmd;
vertex_base() {}
vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
};
typedef vertex_base<int> vertex_i; //-----vertex_i
typedef vertex_base<float> vertex_f; //-----vertex_f
typedef vertex_base<double> vertex_d; //-----vertex_d
//----------------------------------------------------------------row_info
template<class T> struct row_info
{
int x1, x2;
T* ptr;
row_info() {}
row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
};
//----------------------------------------------------------const_row_info
template<class T> struct const_row_info
{
int x1, x2;
const T* ptr;
const_row_info() {}
const_row_info(int x1_, int x2_, const T* ptr_) :
x1(x1_), x2(x2_), ptr(ptr_) {}
};
//------------------------------------------------------------is_equal_eps
template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
{
bool neg1 = v1 < 0.0;
bool neg2 = v2 < 0.0;
if (neg1 != neg2)
return std::fabs(v1) < epsilon && std::fabs(v2) < epsilon;
int int1, int2;
std::frexp(v1, &int1);
std::frexp(v2, &int2);
int min12 = int1 < int2 ? int1 : int2;
v1 = std::ldexp(v1, -min12);
v2 = std::ldexp(v2, -min12);
return std::fabs(v1 - v2) < epsilon;
}
}
#endif

View File

@@ -0,0 +1,159 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
// 4, 7, 10, or 13 vertices.
//
//----------------------------------------------------------------------------
#ifndef AGG_BEZIER_ARC_INCLUDED
#define AGG_BEZIER_ARC_INCLUDED
#include "agg_conv_transform.h"
namespace agg
{
//-----------------------------------------------------------------------
void arc_to_bezier(double cx, double cy, double rx, double ry,
double start_angle, double sweep_angle,
double* curve);
//==============================================================bezier_arc
//
// See implemantaion agg_bezier_arc.cpp
//
class bezier_arc
{
public:
//--------------------------------------------------------------------
bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {}
bezier_arc(double x, double y,
double rx, double ry,
double start_angle,
double sweep_angle)
{
init(x, y, rx, ry, start_angle, sweep_angle);
}
//--------------------------------------------------------------------
void init(double x, double y,
double rx, double ry,
double start_angle,
double sweep_angle);
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_vertex = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if(m_vertex >= m_num_vertices) return path_cmd_stop;
*x = m_vertices[m_vertex];
*y = m_vertices[m_vertex + 1];
m_vertex += 2;
return (m_vertex == 2) ? unsigned(path_cmd_move_to) : m_cmd;
}
// Supplemantary functions. num_vertices() actually returns doubled
// number of vertices. That is, for 1 vertex it returns 2.
//--------------------------------------------------------------------
unsigned num_vertices() const { return m_num_vertices; }
const double* vertices() const { return m_vertices; }
double* vertices() { return m_vertices; }
private:
unsigned m_vertex;
unsigned m_num_vertices;
double m_vertices[26];
unsigned m_cmd;
};
//==========================================================bezier_arc_svg
// Compute an SVG-style bezier arc.
//
// Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
// orientation of the ellipse are defined by two radii (rx, ry)
// and an x-axis-rotation, which indicates how the ellipse as a whole
// is rotated relative to the current coordinate system. The center
// (cx, cy) of the ellipse is calculated automatically to satisfy the
// constraints imposed by the other parameters.
// large-arc-flag and sweep-flag contribute to the automatic calculations
// and help determine how the arc is drawn.
class bezier_arc_svg
{
public:
//--------------------------------------------------------------------
bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
bezier_arc_svg(double x1, double y1,
double rx, double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double x2, double y2) :
m_arc(), m_radii_ok(false)
{
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
}
//--------------------------------------------------------------------
void init(double x1, double y1,
double rx, double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double x2, double y2);
//--------------------------------------------------------------------
bool radii_ok() const { return m_radii_ok; }
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_arc.rewind(0);
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
return m_arc.vertex(x, y);
}
// Supplemantary functions. num_vertices() actually returns doubled
// number of vertices. That is, for 1 vertex it returns 2.
//--------------------------------------------------------------------
unsigned num_vertices() const { return m_arc.num_vertices(); }
const double* vertices() const { return m_arc.vertices(); }
double* vertices() { return m_arc.vertices(); }
private:
bezier_arc m_arc;
bool m_radii_ok;
};
}
#endif

View File

@@ -0,0 +1,54 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_BITSET_ITERATOR_INCLUDED
#define AGG_BITSET_ITERATOR_INCLUDED
#include "agg_basics.h"
namespace agg
{
class bitset_iterator
{
public:
bitset_iterator(const int8u* bits, unsigned offset = 0) :
m_bits(bits + (offset >> 3)),
m_mask(0x80 >> (offset & 7))
{}
void operator ++ ()
{
m_mask >>= 1;
if(m_mask == 0)
{
++m_bits;
m_mask = 0x80;
}
}
unsigned bit() const
{
return (*m_bits) & m_mask;
}
private:
const int8u* m_bits;
int8u m_mask;
};
}
#endif

1505
dep/agg/include/agg_blur.h Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,116 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// bounding_rect function template
//
//----------------------------------------------------------------------------
#ifndef AGG_BOUNDING_RECT_INCLUDED
#define AGG_BOUNDING_RECT_INCLUDED
#include "agg_basics.h"
namespace agg
{
//-----------------------------------------------------------bounding_rect
template<class VertexSource, class GetId, class CoordT>
bool bounding_rect(VertexSource& vs, GetId& gi,
unsigned start, unsigned num,
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
{
unsigned i;
double x;
double y;
bool first = true;
*x1 = CoordT(1);
*y1 = CoordT(1);
*x2 = CoordT(0);
*y2 = CoordT(0);
for(i = 0; i < num; i++)
{
vs.rewind(gi[start + i]);
unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
if(is_vertex(cmd))
{
if(first)
{
*x1 = CoordT(x);
*y1 = CoordT(y);
*x2 = CoordT(x);
*y2 = CoordT(y);
first = false;
}
else
{
if(CoordT(x) < *x1) *x1 = CoordT(x);
if(CoordT(y) < *y1) *y1 = CoordT(y);
if(CoordT(x) > *x2) *x2 = CoordT(x);
if(CoordT(y) > *y2) *y2 = CoordT(y);
}
}
}
}
return *x1 <= *x2 && *y1 <= *y2;
}
//-----------------------------------------------------bounding_rect_single
template<class VertexSource, class CoordT>
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
{
double x;
double y;
bool first = true;
*x1 = CoordT(1);
*y1 = CoordT(1);
*x2 = CoordT(0);
*y2 = CoordT(0);
vs.rewind(path_id);
unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
if(is_vertex(cmd))
{
if(first)
{
*x1 = CoordT(x);
*y1 = CoordT(y);
*x2 = CoordT(x);
*y2 = CoordT(y);
first = false;
}
else
{
if(CoordT(x) < *x1) *x1 = CoordT(x);
if(CoordT(y) < *y1) *y1 = CoordT(y);
if(CoordT(x) > *x2) *x2 = CoordT(x);
if(CoordT(y) > *y2) *y2 = CoordT(y);
}
}
}
return *x1 <= *x2 && *y1 <= *y2;
}
}
#endif

View File

@@ -0,0 +1,76 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class bspline
//
//----------------------------------------------------------------------------
#ifndef AGG_BSPLINE_INCLUDED
#define AGG_BSPLINE_INCLUDED
#include "agg_array.h"
namespace agg
{
//----------------------------------------------------------------bspline
// A very simple class of Bi-cubic Spline interpolation.
// First call init(num, x[], y[]) where num - number of source points,
// x, y - arrays of X and Y values respectively. Here Y must be a function
// of X. It means that all the X-coordinates must be arranged in the ascending
// order.
// Then call get(x) that calculates a value Y for the respective X.
// The class supports extrapolation, i.e. you can call get(x) where x is
// outside the given with init() X-range. Extrapolation is a simple linear
// function.
//
// See Implementation agg_bspline.cpp
//------------------------------------------------------------------------
class bspline
{
public:
bspline();
bspline(int num);
bspline(int num, const double* x, const double* y);
void init(int num);
void add_point(double x, double y);
void prepare();
void init(int num, const double* x, const double* y);
double get(double x) const;
double get_stateful(double x) const;
private:
bspline(const bspline&);
const bspline& operator = (const bspline&);
static void bsearch(int n, const double *x, double x0, int *i);
double extrapolation_left(double x) const;
double extrapolation_right(double x) const;
double interpolation(double x, int i) const;
int m_max;
int m_num;
double* m_x;
double* m_y;
pod_array<double> m_am;
mutable int m_last_idx;
};
}
#endif

View File

@@ -0,0 +1,333 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Liang-Barsky clipping
//
//----------------------------------------------------------------------------
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
#include "agg_basics.h"
namespace agg
{
//------------------------------------------------------------------------
enum clipping_flags_e
{
clipping_flags_x1_clipped = 4,
clipping_flags_x2_clipped = 1,
clipping_flags_y1_clipped = 8,
clipping_flags_y2_clipped = 2,
clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
};
//----------------------------------------------------------clipping_flags
// Determine the clipping code of the vertex according to the
// Cyrus-Beck line clipping algorithm
//
// | |
// 0110 | 0010 | 0011
// | |
// -------+--------+-------- clip_box.y2
// | |
// 0100 | 0000 | 0001
// | |
// -------+--------+-------- clip_box.y1
// | |
// 1100 | 1000 | 1001
// | |
// clip_box.x1 clip_box.x2
//
//
template<class T>
inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
{
return (x > clip_box.x2) |
((y > clip_box.y2) << 1) |
((x < clip_box.x1) << 2) |
((y < clip_box.y1) << 3);
}
//--------------------------------------------------------clipping_flags_x
template<class T>
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
{
return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
}
//--------------------------------------------------------clipping_flags_y
template<class T>
inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
{
return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
}
//-------------------------------------------------------clip_liang_barsky
template<class T>
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
const rect_base<T>& clip_box,
T* x, T* y)
{
const double nearzero = 1e-30;
double deltax = x2 - x1;
double deltay = y2 - y1;
double xin;
double xout;
double yin;
double yout;
double tinx;
double tiny;
double toutx;
double touty;
double tin1;
double tin2;
double tout1;
unsigned np = 0;
if(deltax == 0.0)
{
// bump off of the vertical
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
}
if(deltay == 0.0)
{
// bump off of the horizontal
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
}
if(deltax > 0.0)
{
// points to right
xin = clip_box.x1;
xout = clip_box.x2;
}
else
{
xin = clip_box.x2;
xout = clip_box.x1;
}
if(deltay > 0.0)
{
// points up
yin = clip_box.y1;
yout = clip_box.y2;
}
else
{
yin = clip_box.y2;
yout = clip_box.y1;
}
tinx = (xin - x1) / deltax;
tiny = (yin - y1) / deltay;
if (tinx < tiny)
{
// hits x first
tin1 = tinx;
tin2 = tiny;
}
else
{
// hits y first
tin1 = tiny;
tin2 = tinx;
}
if(tin1 <= 1.0)
{
if(0.0 < tin1)
{
*x++ = (T)xin;
*y++ = (T)yin;
++np;
}
if(tin2 <= 1.0)
{
toutx = (xout - x1) / deltax;
touty = (yout - y1) / deltay;
tout1 = (toutx < touty) ? toutx : touty;
if(tin2 > 0.0 || tout1 > 0.0)
{
if(tin2 <= tout1)
{
if(tin2 > 0.0)
{
if(tinx > tiny)
{
*x++ = (T)xin;
*y++ = (T)(y1 + tinx * deltay);
}
else
{
*x++ = (T)(x1 + tiny * deltax);
*y++ = (T)yin;
}
++np;
}
if(tout1 < 1.0)
{
if(toutx < touty)
{
*x++ = (T)xout;
*y++ = (T)(y1 + toutx * deltay);
}
else
{
*x++ = (T)(x1 + touty * deltax);
*y++ = (T)yout;
}
}
else
{
*x++ = x2;
*y++ = y2;
}
++np;
}
else
{
if(tinx > tiny)
{
*x++ = (T)xin;
*y++ = (T)yout;
}
else
{
*x++ = (T)xout;
*y++ = (T)yin;
}
++np;
}
}
}
}
return np;
}
//----------------------------------------------------------------------------
template<class T>
bool clip_move_point(T x1, T y1, T x2, T y2,
const rect_base<T>& clip_box,
T* x, T* y, unsigned flags)
{
T bound;
if(flags & clipping_flags_x_clipped)
{
if(x1 == x2)
{
return false;
}
bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
*y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
*x = bound;
}
flags = clipping_flags_y(*y, clip_box);
if(flags & clipping_flags_y_clipped)
{
if(y1 == y2)
{
return false;
}
bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
*x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
*y = bound;
}
return true;
}
//-------------------------------------------------------clip_line_segment
// Returns: ret >= 4 - Fully clipped
// (ret & 1) != 0 - First point has been moved
// (ret & 2) != 0 - Second point has been moved
//
template<class T>
unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
const rect_base<T>& clip_box)
{
unsigned f1 = clipping_flags(*x1, *y1, clip_box);
unsigned f2 = clipping_flags(*x2, *y2, clip_box);
unsigned ret = 0;
if((f2 | f1) == 0)
{
// Fully visible
return 0;
}
if((f1 & clipping_flags_x_clipped) != 0 &&
(f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
{
// Fully clipped
return 4;
}
if((f1 & clipping_flags_y_clipped) != 0 &&
(f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
{
// Fully clipped
return 4;
}
T tx1 = *x1;
T ty1 = *y1;
T tx2 = *x2;
T ty2 = *y2;
if(f1)
{
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
{
return 4;
}
if(*x1 == *x2 && *y1 == *y2)
{
return 4;
}
ret |= 1;
}
if(f2)
{
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
{
return 4;
}
if(*x1 == *x2 && *y1 == *y2)
{
return 4;
}
ret |= 2;
}
return ret;
}
}
#endif

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
#ifndef AGG_CONFIG_INCLUDED
#define AGG_CONFIG_INCLUDED
// This file can be used to redefine certain data types.
//---------------------------------------
// 1. Default basic types such as:
//
// AGG_INT8
// AGG_INT8U
// AGG_INT16
// AGG_INT16U
// AGG_INT32
// AGG_INT32U
// AGG_INT64
// AGG_INT64U
//
// Just replace this file with new defines if necessary.
// For example, if your compiler doesn't have a 64 bit integer type
// you can still use AGG if you define the follows:
//
// #define AGG_INT64 int
// #define AGG_INT64U unsigned
//
// It will result in overflow in 16 bit-per-component image/pattern resampling
// but it won't result any crash and the rest of the library will remain
// fully functional.
//---------------------------------------
// 2. Default rendering_buffer type. Can be:
//
// Provides faster access for massive pixel operations,
// such as blur, image filtering:
// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
//
// Provides cheaper creation and destruction (no mem allocs):
// #define AGG_RENDERING_BUFFER row_accessor<int8u>
//
// You can still use both of them simultaneously in your applications
// This #define is used only for default rendering_buffer type,
// in short hand typedefs like pixfmt_rgba32.
#endif

View File

@@ -0,0 +1,157 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
#include "agg_basics.h"
namespace agg
{
//------------------------------------------------------------null_markers
struct null_markers
{
void remove_all() {}
void add_vertex(double, double, unsigned) {}
void prepare_src() {}
void rewind(unsigned) {}
unsigned vertex(double*, double*) { return path_cmd_stop; }
};
//------------------------------------------------------conv_adaptor_vcgen
template<class VertexSource,
class Generator,
class Markers=null_markers> class conv_adaptor_vcgen
{
enum status
{
initial,
accumulate,
generate
};
public:
explicit conv_adaptor_vcgen(VertexSource& source) :
m_source(&source),
m_status(initial)
{}
void attach(VertexSource& source) { m_source = &source; }
Generator& generator() { return m_generator; }
const Generator& generator() const { return m_generator; }
Markers& markers() { return m_markers; }
const Markers& markers() const { return m_markers; }
void rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_status = initial;
}
unsigned vertex(double* x, double* y);
private:
// Prohibit copying
conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
VertexSource* m_source;
Generator m_generator;
Markers m_markers;
status m_status;
unsigned m_last_cmd;
double m_start_x;
double m_start_y;
};
//------------------------------------------------------------------------
template<class VertexSource, class Generator, class Markers>
unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
bool done = false;
while(!done)
{
switch(m_status)
{
case initial:
m_markers.remove_all();
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
m_status = accumulate;
case accumulate:
if(is_stop(m_last_cmd)) return path_cmd_stop;
m_generator.remove_all();
m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
for(;;)
{
cmd = m_source->vertex(x, y);
if(is_vertex(cmd))
{
m_last_cmd = cmd;
if(is_move_to(cmd))
{
m_start_x = *x;
m_start_y = *y;
break;
}
m_generator.add_vertex(*x, *y, cmd);
m_markers.add_vertex(*x, *y, path_cmd_line_to);
}
else
{
if(is_stop(cmd))
{
m_last_cmd = path_cmd_stop;
break;
}
if(is_end_poly(cmd))
{
m_generator.add_vertex(*x, *y, cmd);
break;
}
}
}
m_generator.rewind(0);
m_status = generate;
case generate:
cmd = m_generator.vertex(x, y);
if(is_stop(cmd))
{
m_status = accumulate;
break;
}
done = true;
break;
}
}
return cmd;
}
}
#endif

View File

@@ -0,0 +1,159 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
#include "agg_basics.h"
namespace agg
{
//======================================================conv_adaptor_vpgen
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
{
public:
explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
void attach(VertexSource& source) { m_source = &source; }
VPGen& vpgen() { return m_vpgen; }
const VPGen& vpgen() const { return m_vpgen; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
const conv_adaptor_vpgen<VertexSource, VPGen>&
operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
VertexSource* m_source;
VPGen m_vpgen;
double m_start_x;
double m_start_y;
unsigned m_poly_flags;
int m_vertices;
};
//------------------------------------------------------------------------
template<class VertexSource, class VPGen>
void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_vpgen.reset();
m_start_x = 0;
m_start_y = 0;
m_poly_flags = 0;
m_vertices = 0;
}
//------------------------------------------------------------------------
template<class VertexSource, class VPGen>
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
for(;;)
{
cmd = m_vpgen.vertex(x, y);
if(!is_stop(cmd)) break;
if(m_poly_flags && !m_vpgen.auto_unclose())
{
*x = 0.0;
*y = 0.0;
cmd = m_poly_flags;
m_poly_flags = 0;
break;
}
if(m_vertices < 0)
{
if(m_vertices < -1)
{
m_vertices = 0;
return path_cmd_stop;
}
m_vpgen.move_to(m_start_x, m_start_y);
m_vertices = 1;
continue;
}
double tx, ty;
cmd = m_source->vertex(&tx, &ty);
if(is_vertex(cmd))
{
if(is_move_to(cmd))
{
if(m_vpgen.auto_close() && m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
m_poly_flags = path_cmd_end_poly | path_flags_close;
m_start_x = tx;
m_start_y = ty;
m_vertices = -1;
continue;
}
m_vpgen.move_to(tx, ty);
m_start_x = tx;
m_start_y = ty;
m_vertices = 1;
}
else
{
m_vpgen.line_to(tx, ty);
++m_vertices;
}
}
else
{
if(is_end_poly(cmd))
{
m_poly_flags = cmd;
if(is_closed(cmd) || m_vpgen.auto_close())
{
if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
if(m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
}
m_vertices = 0;
}
}
else
{
// path_cmd_stop
if(m_vpgen.auto_close() && m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
m_poly_flags = path_cmd_end_poly | path_flags_close;
m_vertices = -2;
continue;
}
break;
}
}
}
return cmd;
}
}
#endif

View File

@@ -0,0 +1,48 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_BSPLINE_INCLUDED
#define AGG_CONV_BSPLINE_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_bspline.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
{
//---------------------------------------------------------conv_bspline
template<class VertexSource>
struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
conv_bspline(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
double interpolation_step() const { return base_type::generator().interpolation_step(); }
private:
conv_bspline(const conv_bspline<VertexSource>&);
const conv_bspline<VertexSource>&
operator = (const conv_bspline<VertexSource>&);
};
}
#endif

View File

@@ -0,0 +1,63 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Polygon clipping converter
// There an optimized Liang-Basky algorithm is used.
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
// break a closed polygon into two or more ones, instead, there will be
// degenerate edges coinciding with the respective clipping boundaries.
// This is a sub-optimal solution, because that optimization would require
// extra, rather expensive math while the rasterizer tolerates it quite well,
// without any considerable overhead.
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED
#define AGG_CONV_CLIP_POLYGON_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_clip_polygon.h"
namespace agg
{
//=======================================================conv_clip_polygon
template<class VertexSource>
struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>
{
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type;
conv_clip_polygon(VertexSource& vs) :
conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
void clip_box(double x1, double y1, double x2, double y2)
{
base_type::vpgen().clip_box(x1, y1, x2, y2);
}
double x1() const { return base_type::vpgen().x1(); }
double y1() const { return base_type::vpgen().y1(); }
double x2() const { return base_type::vpgen().x2(); }
double y2() const { return base_type::vpgen().y2(); }
private:
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
const conv_clip_polygon<VertexSource>&
operator = (const conv_clip_polygon<VertexSource>&);
};
}
#endif

View File

@@ -0,0 +1,63 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// polyline clipping converter
// There an optimized Liang-Basky algorithm is used.
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
// break a closed polyline into two or more ones, instead, there will be
// degenerate edges coinciding with the respective clipping boundaries.
// This is a sub-optimal solution, because that optimization would require
// extra, rather expensive math while the rasterizer tolerates it quite well,
// without any considerable overhead.
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CLIP_polyline_INCLUDED
#define AGG_CONV_CLIP_polyline_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_clip_polyline.h"
namespace agg
{
//=======================================================conv_clip_polyline
template<class VertexSource>
struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>
{
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
conv_clip_polyline(VertexSource& vs) :
conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {}
void clip_box(double x1, double y1, double x2, double y2)
{
base_type::vpgen().clip_box(x1, y1, x2, y2);
}
double x1() const { return base_type::vpgen().x1(); }
double y1() const { return base_type::vpgen().y1(); }
double x2() const { return base_type::vpgen().x2(); }
double y2() const { return base_type::vpgen().y2(); }
private:
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
const conv_clip_polyline<VertexSource>&
operator = (const conv_clip_polyline<VertexSource>&);
};
}
#endif

View File

@@ -0,0 +1,125 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED
#define AGG_CONV_CLOSE_POLYGON_INCLUDED
#include "agg_basics.h"
namespace agg
{
//======================================================conv_close_polygon
template<class VertexSource> class conv_close_polygon
{
public:
explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
conv_close_polygon(const conv_close_polygon<VertexSource>&);
const conv_close_polygon<VertexSource>&
operator = (const conv_close_polygon<VertexSource>&);
VertexSource* m_source;
unsigned m_cmd[2];
double m_x[2];
double m_y[2];
unsigned m_vertex;
bool m_line_to;
};
//------------------------------------------------------------------------
template<class VertexSource>
void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_vertex = 2;
m_line_to = false;
}
//------------------------------------------------------------------------
template<class VertexSource>
unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
for(;;)
{
if(m_vertex < 2)
{
*x = m_x[m_vertex];
*y = m_y[m_vertex];
cmd = m_cmd[m_vertex];
++m_vertex;
break;
}
cmd = m_source->vertex(x, y);
if(is_end_poly(cmd))
{
cmd |= path_flags_close;
break;
}
if(is_stop(cmd))
{
if(m_line_to)
{
m_cmd[0] = path_cmd_end_poly | path_flags_close;
m_cmd[1] = path_cmd_stop;
m_vertex = 0;
m_line_to = false;
continue;
}
break;
}
if(is_move_to(cmd))
{
if(m_line_to)
{
m_x[0] = 0.0;
m_y[0] = 0.0;
m_cmd[0] = path_cmd_end_poly | path_flags_close;
m_x[1] = *x;
m_y[1] = *y;
m_cmd[1] = cmd;
m_vertex = 0;
m_line_to = false;
continue;
}
break;
}
if(is_vertex(cmd))
{
m_line_to = true;
break;
}
}
return cmd;
}
}
#endif

View File

@@ -0,0 +1,73 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CONCAT_INCLUDED
#define AGG_CONV_CONCAT_INCLUDED
#include "agg_basics.h"
namespace agg
{
//=============================================================conv_concat
// Concatenation of two paths. Usually used to combine lines or curves
// with markers such as arrowheads
template<class VS1, class VS2> class conv_concat
{
public:
conv_concat(VS1& source1, VS2& source2) :
m_source1(&source1), m_source2(&source2), m_status(2) {}
void attach1(VS1& source) { m_source1 = &source; }
void attach2(VS2& source) { m_source2 = &source; }
void rewind(unsigned path_id)
{
m_source1->rewind(path_id);
m_source2->rewind(0);
m_status = 0;
}
unsigned vertex(double* x, double* y)
{
unsigned cmd;
if(m_status == 0)
{
cmd = m_source1->vertex(x, y);
if(!is_stop(cmd)) return cmd;
m_status = 1;
}
if(m_status == 1)
{
cmd = m_source2->vertex(x, y);
if(!is_stop(cmd)) return cmd;
m_status = 2;
}
return path_cmd_stop;
}
private:
conv_concat(const conv_concat<VS1, VS2>&);
const conv_concat<VS1, VS2>&
operator = (const conv_concat<VS1, VS2>&);
VS1* m_source1;
VS2* m_source2;
int m_status;
};
}
#endif

View File

@@ -0,0 +1,65 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// conv_stroke
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CONTOUR_INCLUDED
#define AGG_CONV_CONTOUR_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_contour.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
{
//-----------------------------------------------------------conv_contour
template<class VertexSource>
struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
conv_contour(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
{
}
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
void width(double w) { base_type::generator().width(w); }
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
line_join_e line_join() const { return base_type::generator().line_join(); }
inner_join_e inner_join() const { return base_type::generator().inner_join(); }
double width() const { return base_type::generator().width(); }
double miter_limit() const { return base_type::generator().miter_limit(); }
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
double approximation_scale() const { return base_type::generator().approximation_scale(); }
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
private:
conv_contour(const conv_contour<VertexSource>&);
const conv_contour<VertexSource>&
operator = (const conv_contour<VertexSource>&);
};
}
#endif

View File

@@ -0,0 +1,201 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// classes conv_curve
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CURVE_INCLUDED
#define AGG_CONV_CURVE_INCLUDED
#include "agg_basics.h"
#include "agg_curves.h"
namespace agg
{
//---------------------------------------------------------------conv_curve
// Curve converter class. Any path storage can have Bezier curves defined
// by their control points. There're two types of curves supported: curve3
// and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
// point. Curve4 has 2 control points (4 points in total) and can be used
// to interpolate more complicated curves. Curve4, unlike curve3 can be used
// to approximate arcs, both circular and elliptical. Curves are approximated
// with straight lines and one of the approaches is just to store the whole
// sequence of vertices that approximate our curve. It takes additional
// memory, and at the same time the consecutive vertices can be calculated
// on demand.
//
// Initially, path storages are not suppose to keep all the vertices of the
// curves (although, nothing prevents us from doing so). Instead, path_storage
// keeps only vertices, needed to calculate a curve on demand. Those vertices
// are marked with special commands. So, if the path_storage contains curves
// (which are not real curves yet), and we render this storage directly,
// all we will see is only 2 or 3 straight line segments (for curve3 and
// curve4 respectively). If we need to see real curves drawn we need to
// include this class into the conversion pipeline.
//
// Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4
// and converts these vertices into a move_to/line_to sequence.
//-----------------------------------------------------------------------
template<class VertexSource,
class Curve3=curve3,
class Curve4=curve4> class conv_curve
{
public:
typedef Curve3 curve3_type;
typedef Curve4 curve4_type;
typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
explicit conv_curve(VertexSource& source) :
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
void attach(VertexSource& source) { m_source = &source; }
void approximation_method(curve_approximation_method_e v)
{
m_curve3.approximation_method(v);
m_curve4.approximation_method(v);
}
curve_approximation_method_e approximation_method() const
{
return m_curve4.approximation_method();
}
void approximation_scale(double s)
{
m_curve3.approximation_scale(s);
m_curve4.approximation_scale(s);
}
double approximation_scale() const
{
return m_curve4.approximation_scale();
}
void angle_tolerance(double v)
{
m_curve3.angle_tolerance(v);
m_curve4.angle_tolerance(v);
}
double angle_tolerance() const
{
return m_curve4.angle_tolerance();
}
void cusp_limit(double v)
{
m_curve3.cusp_limit(v);
m_curve4.cusp_limit(v);
}
double cusp_limit() const
{
return m_curve4.cusp_limit();
}
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
conv_curve(const self_type&);
const self_type& operator = (const self_type&);
VertexSource* m_source;
double m_last_x;
double m_last_y;
curve3_type m_curve3;
curve4_type m_curve4;
};
//------------------------------------------------------------------------
template<class VertexSource, class Curve3, class Curve4>
void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_last_x = 0.0;
m_last_y = 0.0;
m_curve3.reset();
m_curve4.reset();
}
//------------------------------------------------------------------------
template<class VertexSource, class Curve3, class Curve4>
unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
{
if(!is_stop(m_curve3.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
if(!is_stop(m_curve4.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
double ct2_x = 0;
double ct2_y = 0;
double end_x = 0;
double end_y = 0;
unsigned cmd = m_source->vertex(x, y);
switch(cmd)
{
case path_cmd_curve3:
m_source->vertex(&end_x, &end_y);
m_curve3.init(m_last_x, m_last_y,
*x, *y,
end_x, end_y);
m_curve3.vertex(x, y); // First call returns path_cmd_move_to
m_curve3.vertex(x, y); // This is the first vertex of the curve
cmd = path_cmd_line_to;
break;
case path_cmd_curve4:
m_source->vertex(&ct2_x, &ct2_y);
m_source->vertex(&end_x, &end_y);
m_curve4.init(m_last_x, m_last_y,
*x, *y,
ct2_x, ct2_y,
end_x, end_y);
m_curve4.vertex(x, y); // First call returns path_cmd_move_to
m_curve4.vertex(x, y); // This is the first vertex of the curve
cmd = path_cmd_line_to;
break;
}
m_last_x = *x;
m_last_y = *y;
return cmd;
}
}
#endif

View File

@@ -0,0 +1,68 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// conv_dash
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_DASH_INCLUDED
#define AGG_CONV_DASH_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_dash.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
{
//---------------------------------------------------------------conv_dash
template<class VertexSource, class Markers=null_markers>
struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>
{
typedef Markers marker_type;
typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type;
conv_dash(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
{
}
void remove_all_dashes()
{
base_type::generator().remove_all_dashes();
}
void add_dash(double dash_len, double gap_len)
{
base_type::generator().add_dash(dash_len, gap_len);
}
void dash_start(double ds)
{
base_type::generator().dash_start(ds);
}
void shorten(double s) { base_type::generator().shorten(s); }
double shorten() const { return base_type::generator().shorten(); }
private:
conv_dash(const conv_dash<VertexSource, Markers>&);
const conv_dash<VertexSource, Markers>&
operator = (const conv_dash<VertexSource, Markers>&);
};
}
#endif

View File

@@ -0,0 +1,432 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// General Polygon Clipper based on the GPC library by Alan Murta
// Union, Intersection, XOR, A-B, B-A
// Contact the author if you intend to use it in commercial applications!
// http://www.cs.man.ac.uk/aig/staff/alan/software/
// Alan Murta (email: gpc@cs.man.ac.uk)
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_GPC_INCLUDED
#define AGG_CONV_GPC_INCLUDED
#include <cstring>
#include "agg_basics.h"
#include "agg_array.h"
extern "C"
{
#include "gpc.h"
}
namespace agg
{
enum gpc_op_e
{
gpc_or,
gpc_and,
gpc_xor,
gpc_a_minus_b,
gpc_b_minus_a
};
//================================================================conv_gpc
template<class VSA, class VSB> class conv_gpc
{
enum status
{
status_move_to,
status_line_to,
status_stop
};
struct contour_header_type
{
int num_vertices;
int hole_flag;
gpc_vertex* vertices;
};
typedef pod_bvector<gpc_vertex, 8> vertex_array_type;
typedef pod_bvector<contour_header_type, 6> contour_header_array_type;
public:
typedef VSA source_a_type;
typedef VSB source_b_type;
typedef conv_gpc<source_a_type, source_b_type> self_type;
~conv_gpc()
{
free_gpc_data();
}
conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
m_src_a(&a),
m_src_b(&b),
m_status(status_move_to),
m_vertex(-1),
m_contour(-1),
m_operation(op)
{
std::memset(&m_poly_a, 0, sizeof(m_poly_a));
std::memset(&m_poly_b, 0, sizeof(m_poly_b));
std::memset(&m_result, 0, sizeof(m_result));
}
void attach1(VSA& source) { m_src_a = &source; }
void attach2(VSB& source) { m_src_b = &source; }
void operation(gpc_op_e v) { m_operation = v; }
// Vertex Source Interface
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
conv_gpc(const conv_gpc<VSA, VSB>&);
const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
//--------------------------------------------------------------------
void free_polygon(gpc_polygon& p);
void free_result();
void free_gpc_data();
void start_contour();
void add_vertex(double x, double y);
void end_contour(unsigned orientation);
void make_polygon(gpc_polygon& p);
void start_extracting();
bool next_contour();
bool next_vertex(double* x, double* y);
//--------------------------------------------------------------------
template<class VS> void add(VS& src, gpc_polygon& p)
{
unsigned cmd;
double x, y;
double start_x = 0.0;
double start_y = 0.0;
bool line_to = false;
unsigned orientation = 0;
m_contour_accumulator.remove_all();
while(!is_stop(cmd = src.vertex(&x, &y)))
{
if(is_vertex(cmd))
{
if(is_move_to(cmd))
{
if(line_to)
{
end_contour(orientation);
orientation = 0;
}
start_contour();
start_x = x;
start_y = y;
}
add_vertex(x, y);
line_to = true;
}
else
{
if(is_end_poly(cmd))
{
orientation = get_orientation(cmd);
if(line_to && is_closed(cmd))
{
add_vertex(start_x, start_y);
}
}
}
}
if(line_to)
{
end_contour(orientation);
}
make_polygon(p);
}
private:
//--------------------------------------------------------------------
source_a_type* m_src_a;
source_b_type* m_src_b;
status m_status;
int m_vertex;
int m_contour;
gpc_op_e m_operation;
vertex_array_type m_vertex_accumulator;
contour_header_array_type m_contour_accumulator;
gpc_polygon m_poly_a;
gpc_polygon m_poly_b;
gpc_polygon m_result;
};
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
{
int i;
for(i = 0; i < p.num_contours; i++)
{
pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex,
p.contour[i].num_vertices);
}
pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
std::memset(&p, 0, sizeof(gpc_polygon));
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::free_result()
{
if(m_result.contour)
{
gpc_free_polygon(&m_result);
}
std::memset(&m_result, 0, sizeof(m_result));
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::free_gpc_data()
{
free_polygon(m_poly_a);
free_polygon(m_poly_b);
free_result();
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::start_contour()
{
contour_header_type h;
std::memset(&h, 0, sizeof(h));
m_contour_accumulator.add(h);
m_vertex_accumulator.remove_all();
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
{
gpc_vertex v;
v.x = x;
v.y = y;
m_vertex_accumulator.add(v);
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::end_contour(unsigned /*orientation*/)
{
if(m_contour_accumulator.size())
{
if(m_vertex_accumulator.size() > 2)
{
contour_header_type& h =
m_contour_accumulator[m_contour_accumulator.size() - 1];
h.num_vertices = m_vertex_accumulator.size();
h.hole_flag = 0;
// TO DO: Clarify the "holes"
//if(is_cw(orientation)) h.hole_flag = 1;
h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices);
gpc_vertex* d = h.vertices;
int i;
for(i = 0; i < h.num_vertices; i++)
{
const gpc_vertex& s = m_vertex_accumulator[i];
d->x = s.x;
d->y = s.y;
++d;
}
}
else
{
m_vertex_accumulator.remove_last();
}
}
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
{
free_polygon(p);
if(m_contour_accumulator.size())
{
p.num_contours = m_contour_accumulator.size();
p.hole = 0;
p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
int i;
gpc_vertex_list* pv = p.contour;
for(i = 0; i < p.num_contours; i++)
{
const contour_header_type& h = m_contour_accumulator[i];
pv->num_vertices = h.num_vertices;
pv->vertex = h.vertices;
++pv;
}
}
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::start_extracting()
{
m_status = status_move_to;
m_contour = -1;
m_vertex = -1;
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
bool conv_gpc<VSA, VSB>::next_contour()
{
if(++m_contour < m_result.num_contours)
{
m_vertex = -1;
return true;
}
return false;
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
{
const gpc_vertex_list& vlist = m_result.contour[m_contour];
if(++m_vertex < vlist.num_vertices)
{
const gpc_vertex& v = vlist.vertex[m_vertex];
*x = v.x;
*y = v.y;
return true;
}
return false;
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::rewind(unsigned path_id)
{
free_result();
m_src_a->rewind(path_id);
m_src_b->rewind(path_id);
add(*m_src_a, m_poly_a);
add(*m_src_b, m_poly_b);
switch(m_operation)
{
case gpc_or:
gpc_polygon_clip(GPC_UNION,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_and:
gpc_polygon_clip(GPC_INT,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_xor:
gpc_polygon_clip(GPC_XOR,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_a_minus_b:
gpc_polygon_clip(GPC_DIFF,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_b_minus_a:
gpc_polygon_clip(GPC_DIFF,
&m_poly_b,
&m_poly_a,
&m_result);
break;
}
start_extracting();
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
{
if(m_status == status_move_to)
{
if(next_contour())
{
if(next_vertex(x, y))
{
m_status = status_line_to;
return path_cmd_move_to;
}
m_status = status_stop;
return path_cmd_end_poly | path_flags_close;
}
}
else
{
if(next_vertex(x, y))
{
return path_cmd_line_to;
}
else
{
m_status = status_move_to;
}
return path_cmd_end_poly | path_flags_close;
}
return path_cmd_stop;
}
}
#endif

View File

@@ -0,0 +1,149 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// conv_marker
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_MARKER_INCLUDED
#define AGG_CONV_MARKER_INCLUDED
#include <cmath>
#include "agg_basics.h"
#include "agg_trans_affine.h"
namespace agg
{
//-------------------------------------------------------------conv_marker
template<class MarkerLocator, class MarkerShapes>
class conv_marker
{
public:
conv_marker(MarkerLocator& ml, MarkerShapes& ms);
trans_affine& transform() { return m_transform; }
const trans_affine& transform() const { return m_transform; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&);
const conv_marker<MarkerLocator, MarkerShapes>&
operator = (const conv_marker<MarkerLocator, MarkerShapes>&);
enum status_e
{
initial,
markers,
polygon,
stop
};
MarkerLocator* m_marker_locator;
MarkerShapes* m_marker_shapes;
trans_affine m_transform;
trans_affine m_mtx;
status_e m_status;
unsigned m_marker;
unsigned m_num_markers;
};
//------------------------------------------------------------------------
template<class MarkerLocator, class MarkerShapes>
conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) :
m_marker_locator(&ml),
m_marker_shapes(&ms),
m_status(initial),
m_marker(0),
m_num_markers(1)
{
}
//------------------------------------------------------------------------
template<class MarkerLocator, class MarkerShapes>
void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned)
{
m_status = initial;
m_marker = 0;
m_num_markers = 1;
}
//------------------------------------------------------------------------
template<class MarkerLocator, class MarkerShapes>
unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_move_to;
double x1, y1, x2, y2;
while(!is_stop(cmd))
{
switch(m_status)
{
case initial:
if(m_num_markers == 0)
{
cmd = path_cmd_stop;
break;
}
m_marker_locator->rewind(m_marker);
++m_marker;
m_num_markers = 0;
m_status = markers;
case markers:
if(is_stop(m_marker_locator->vertex(&x1, &y1)))
{
m_status = initial;
break;
}
if(is_stop(m_marker_locator->vertex(&x2, &y2)))
{
m_status = initial;
break;
}
++m_num_markers;
m_mtx = m_transform;
m_mtx *= trans_affine_rotation(std::atan2(y2 - y1, x2 - x1));
m_mtx *= trans_affine_translation(x1, y1);
m_marker_shapes->rewind(m_marker - 1);
m_status = polygon;
case polygon:
cmd = m_marker_shapes->vertex(x, y);
if(is_stop(cmd))
{
cmd = path_cmd_move_to;
m_status = markers;
break;
}
m_mtx.transform(x, y);
return cmd;
case stop:
cmd = path_cmd_stop;
break;
}
}
return cmd;
}
}
#endif

View File

@@ -0,0 +1,51 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_MARKER_ADAPTOR_INCLUDED
#define AGG_CONV_MARKER_ADAPTOR_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vcgen.h"
#include "agg_vcgen_vertex_sequence.h"
namespace agg
{
//=====================================================conv_marker_adaptor
template<class VertexSource, class Markers=null_markers>
struct conv_marker_adaptor :
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>
{
typedef Markers marker_type;
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type;
conv_marker_adaptor(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs)
{
}
void shorten(double s) { base_type::generator().shorten(s); }
double shorten() const { return base_type::generator().shorten(); }
private:
conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
const conv_marker_adaptor<VertexSource, Markers>&
operator = (const conv_marker_adaptor<VertexSource, Markers>&);
};
}
#endif

View File

@@ -0,0 +1,48 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_SEGMENTATOR_INCLUDED
#define AGG_CONV_SEGMENTATOR_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_segmentator.h"
namespace agg
{
//========================================================conv_segmentator
template<class VertexSource>
struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator>
{
typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type;
conv_segmentator(VertexSource& vs) :
conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {}
void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); }
double approximation_scale() const { return base_type::vpgen().approximation_scale(); }
private:
conv_segmentator(const conv_segmentator<VertexSource>&);
const conv_segmentator<VertexSource>&
operator = (const conv_segmentator<VertexSource>&);
};
}
#endif

View File

@@ -0,0 +1,50 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_SHORTEN_PATH_INCLUDED
#define AGG_CONV_SHORTEN_PATH_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vcgen.h"
#include "agg_vcgen_vertex_sequence.h"
namespace agg
{
//=======================================================conv_shorten_path
template<class VertexSource> class conv_shorten_path :
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>
{
public:
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type;
conv_shorten_path(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs)
{
}
void shorten(double s) { base_type::generator().shorten(s); }
double shorten() const { return base_type::generator().shorten(); }
private:
conv_shorten_path(const conv_shorten_path<VertexSource>&);
const conv_shorten_path<VertexSource>&
operator = (const conv_shorten_path<VertexSource>&);
};
}
#endif

View File

@@ -0,0 +1,80 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Smooth polygon generator
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED
#define AGG_CONV_SMOOTH_POLY1_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_smooth_poly1.h"
#include "agg_conv_adaptor_vcgen.h"
#include "agg_conv_curve.h"
namespace agg
{
//-------------------------------------------------------conv_smooth_poly1
template<class VertexSource>
struct conv_smooth_poly1 :
public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type;
conv_smooth_poly1(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs)
{
}
void smooth_value(double v) { base_type::generator().smooth_value(v); }
double smooth_value() const { return base_type::generator().smooth_value(); }
private:
conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&);
const conv_smooth_poly1<VertexSource>&
operator = (const conv_smooth_poly1<VertexSource>&);
};
//-------------------------------------------------conv_smooth_poly1_curve
template<class VertexSource>
struct conv_smooth_poly1_curve :
public conv_curve<conv_smooth_poly1<VertexSource> >
{
conv_smooth_poly1_curve(VertexSource& vs) :
conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth),
m_smooth(vs)
{
}
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
double smooth_value() const { return m_smooth.generator().smooth_value(); }
private:
conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&);
const conv_smooth_poly1_curve<VertexSource>&
operator = (const conv_smooth_poly1_curve<VertexSource>&);
conv_smooth_poly1<VertexSource> m_smooth;
};
}
#endif

View File

@@ -0,0 +1,73 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// conv_stroke
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_STROKE_INCLUDED
#define AGG_CONV_STROKE_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_stroke.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
{
//-------------------------------------------------------------conv_stroke
template<class VertexSource, class Markers=null_markers>
struct conv_stroke :
public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>
{
typedef Markers marker_type;
typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type;
conv_stroke(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
{
}
void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); }
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
line_cap_e line_cap() const { return base_type::generator().line_cap(); }
line_join_e line_join() const { return base_type::generator().line_join(); }
inner_join_e inner_join() const { return base_type::generator().inner_join(); }
void width(double w) { base_type::generator().width(w); }
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
double width() const { return base_type::generator().width(); }
double miter_limit() const { return base_type::generator().miter_limit(); }
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
double approximation_scale() const { return base_type::generator().approximation_scale(); }
void shorten(double s) { base_type::generator().shorten(s); }
double shorten() const { return base_type::generator().shorten(); }
private:
conv_stroke(const conv_stroke<VertexSource, Markers>&);
const conv_stroke<VertexSource, Markers>&
operator = (const conv_stroke<VertexSource, Markers>&);
};
}
#endif

View File

@@ -0,0 +1,68 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class conv_transform
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_TRANSFORM_INCLUDED
#define AGG_CONV_TRANSFORM_INCLUDED
#include "agg_basics.h"
#include "agg_trans_affine.h"
namespace agg
{
//----------------------------------------------------------conv_transform
template<class VertexSource, class Transformer=trans_affine> class conv_transform
{
public:
conv_transform(VertexSource& source, Transformer& tr) :
m_source(&source), m_trans(&tr) {}
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id)
{
m_source->rewind(path_id);
}
unsigned vertex(double* x, double* y)
{
unsigned cmd = m_source->vertex(x, y);
if(is_vertex(cmd))
{
m_trans->transform(x, y);
}
return cmd;
}
void transformer(Transformer& tr)
{
m_trans = &tr;
}
private:
conv_transform(const conv_transform<VertexSource>&);
const conv_transform<VertexSource>&
operator = (const conv_transform<VertexSource>&);
VertexSource* m_source;
Transformer* m_trans;
};
}
#endif

View File

@@ -0,0 +1,52 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_UNCLOSE_POLYGON_INCLUDED
#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED
#include "agg_basics.h"
namespace agg
{
//====================================================conv_unclose_polygon
template<class VertexSource> class conv_unclose_polygon
{
public:
explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id)
{
m_source->rewind(path_id);
}
unsigned vertex(double* x, double* y)
{
unsigned cmd = m_source->vertex(x, y);
if(is_end_poly(cmd)) cmd &= ~path_flags_close;
return cmd;
}
private:
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
const conv_unclose_polygon<VertexSource>&
operator = (const conv_unclose_polygon<VertexSource>&);
VertexSource* m_source;
};
}
#endif

View File

@@ -0,0 +1,693 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CURVES_INCLUDED
#define AGG_CURVES_INCLUDED
#include "agg_array.h"
namespace agg
{
// See Implementation agg_curves.cpp
//--------------------------------------------curve_approximation_method_e
enum curve_approximation_method_e
{
curve_inc,
curve_div
};
//--------------------------------------------------------------curve3_inc
class curve3_inc
{
public:
curve3_inc() :
m_num_steps(0), m_step(0), m_scale(1.0) { }
curve3_inc(double x1, double y1,
double x2, double y2,
double x3, double y3) :
m_num_steps(0), m_step(0), m_scale(1.0)
{
init(x1, y1, x2, y2, x3, y3);
}
void reset() { m_num_steps = 0; m_step = -1; }
void init(double x1, double y1,
double x2, double y2,
double x3, double y3);
void approximation_method(curve_approximation_method_e) {}
curve_approximation_method_e approximation_method() const { return curve_inc; }
void approximation_scale(double s);
double approximation_scale() const;
void angle_tolerance(double) {}
double angle_tolerance() const { return 0.0; }
void cusp_limit(double) {}
double cusp_limit() const { return 0.0; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
int m_num_steps;
int m_step;
double m_scale;
double m_start_x;
double m_start_y;
double m_end_x;
double m_end_y;
double m_fx;
double m_fy;
double m_dfx;
double m_dfy;
double m_ddfx;
double m_ddfy;
double m_saved_fx;
double m_saved_fy;
double m_saved_dfx;
double m_saved_dfy;
};
//-------------------------------------------------------------curve3_div
class curve3_div
{
public:
curve3_div() :
m_approximation_scale(1.0),
m_angle_tolerance(0.0),
m_count(0)
{}
curve3_div(double x1, double y1,
double x2, double y2,
double x3, double y3) :
m_approximation_scale(1.0),
m_angle_tolerance(0.0),
m_count(0)
{
init(x1, y1, x2, y2, x3, y3);
}
void reset() { m_points.remove_all(); m_count = 0; }
void init(double x1, double y1,
double x2, double y2,
double x3, double y3);
void approximation_method(curve_approximation_method_e) {}
curve_approximation_method_e approximation_method() const { return curve_div; }
void approximation_scale(double s) { m_approximation_scale = s; }
double approximation_scale() const { return m_approximation_scale; }
void angle_tolerance(double a) { m_angle_tolerance = a; }
double angle_tolerance() const { return m_angle_tolerance; }
void cusp_limit(double) {}
double cusp_limit() const { return 0.0; }
void rewind(unsigned)
{
m_count = 0;
}
unsigned vertex(double* x, double* y)
{
if(m_count >= m_points.size()) return path_cmd_stop;
const point_d& p = m_points[m_count++];
*x = p.x;
*y = p.y;
return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
}
private:
void bezier(double x1, double y1,
double x2, double y2,
double x3, double y3);
void recursive_bezier(double x1, double y1,
double x2, double y2,
double x3, double y3,
unsigned level);
double m_approximation_scale;
double m_distance_tolerance_square;
double m_angle_tolerance;
unsigned m_count;
pod_bvector<point_d> m_points;
};
//-------------------------------------------------------------curve4_points
struct curve4_points
{
double cp[8];
curve4_points() {}
curve4_points(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
}
void init(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
}
double operator [] (unsigned i) const { return cp[i]; }
double& operator [] (unsigned i) { return cp[i]; }
};
//-------------------------------------------------------------curve4_inc
class curve4_inc
{
public:
curve4_inc() :
m_num_steps(0), m_step(0), m_scale(1.0) { }
curve4_inc(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4) :
m_num_steps(0), m_step(0), m_scale(1.0)
{
init(x1, y1, x2, y2, x3, y3, x4, y4);
}
curve4_inc(const curve4_points& cp) :
m_num_steps(0), m_step(0), m_scale(1.0)
{
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
}
void reset() { m_num_steps = 0; m_step = -1; }
void init(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4);
void init(const curve4_points& cp)
{
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
}
void approximation_method(curve_approximation_method_e) {}
curve_approximation_method_e approximation_method() const { return curve_inc; }
void approximation_scale(double s);
double approximation_scale() const;
void angle_tolerance(double) {}
double angle_tolerance() const { return 0.0; }
void cusp_limit(double) {}
double cusp_limit() const { return 0.0; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
int m_num_steps;
int m_step;
double m_scale;
double m_start_x;
double m_start_y;
double m_end_x;
double m_end_y;
double m_fx;
double m_fy;
double m_dfx;
double m_dfy;
double m_ddfx;
double m_ddfy;
double m_dddfx;
double m_dddfy;
double m_saved_fx;
double m_saved_fy;
double m_saved_dfx;
double m_saved_dfy;
double m_saved_ddfx;
double m_saved_ddfy;
};
//-------------------------------------------------------catrom_to_bezier
inline curve4_points catrom_to_bezier(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
// Trans. matrix Catmull-Rom to Bezier
//
// 0 1 0 0
// -1/6 1 1/6 0
// 0 1/6 1 -1/6
// 0 0 1 0
//
return curve4_points(
x2,
y2,
(-x1 + 6*x2 + x3) / 6,
(-y1 + 6*y2 + y3) / 6,
( x2 + 6*x3 - x4) / 6,
( y2 + 6*y3 - y4) / 6,
x3,
y3);
}
//-----------------------------------------------------------------------
inline curve4_points
catrom_to_bezier(const curve4_points& cp)
{
return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3],
cp[4], cp[5], cp[6], cp[7]);
}
//-----------------------------------------------------ubspline_to_bezier
inline curve4_points ubspline_to_bezier(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
// Trans. matrix Uniform BSpline to Bezier
//
// 1/6 4/6 1/6 0
// 0 4/6 2/6 0
// 0 2/6 4/6 0
// 0 1/6 4/6 1/6
//
return curve4_points(
(x1 + 4*x2 + x3) / 6,
(y1 + 4*y2 + y3) / 6,
(4*x2 + 2*x3) / 6,
(4*y2 + 2*y3) / 6,
(2*x2 + 4*x3) / 6,
(2*y2 + 4*y3) / 6,
(x2 + 4*x3 + x4) / 6,
(y2 + 4*y3 + y4) / 6);
}
//-----------------------------------------------------------------------
inline curve4_points
ubspline_to_bezier(const curve4_points& cp)
{
return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3],
cp[4], cp[5], cp[6], cp[7]);
}
//------------------------------------------------------hermite_to_bezier
inline curve4_points hermite_to_bezier(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
// Trans. matrix Hermite to Bezier
//
// 1 0 0 0
// 1 0 1/3 0
// 0 1 0 -1/3
// 0 1 0 0
//
return curve4_points(
x1,
y1,
(3*x1 + x3) / 3,
(3*y1 + y3) / 3,
(3*x2 - x4) / 3,
(3*y2 - y4) / 3,
x2,
y2);
}
//-----------------------------------------------------------------------
inline curve4_points
hermite_to_bezier(const curve4_points& cp)
{
return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3],
cp[4], cp[5], cp[6], cp[7]);
}
//-------------------------------------------------------------curve4_div
class curve4_div
{
public:
curve4_div() :
m_approximation_scale(1.0),
m_angle_tolerance(0.0),
m_cusp_limit(0.0),
m_count(0)
{}
curve4_div(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4) :
m_approximation_scale(1.0),
m_angle_tolerance(0.0),
m_cusp_limit(0.0),
m_count(0)
{
init(x1, y1, x2, y2, x3, y3, x4, y4);
}
curve4_div(const curve4_points& cp) :
m_approximation_scale(1.0),
m_angle_tolerance(0.0),
m_count(0)
{
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
}
void reset() { m_points.remove_all(); m_count = 0; }
void init(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4);
void init(const curve4_points& cp)
{
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
}
void approximation_method(curve_approximation_method_e) {}
curve_approximation_method_e approximation_method() const
{
return curve_div;
}
void approximation_scale(double s) { m_approximation_scale = s; }
double approximation_scale() const { return m_approximation_scale; }
void angle_tolerance(double a) { m_angle_tolerance = a; }
double angle_tolerance() const { return m_angle_tolerance; }
void cusp_limit(double v)
{
m_cusp_limit = (v == 0.0) ? 0.0 : pi - v;
}
double cusp_limit() const
{
return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit;
}
void rewind(unsigned)
{
m_count = 0;
}
unsigned vertex(double* x, double* y)
{
if(m_count >= m_points.size()) return path_cmd_stop;
const point_d& p = m_points[m_count++];
*x = p.x;
*y = p.y;
return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
}
private:
void bezier(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4);
void recursive_bezier(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4,
unsigned level);
double m_approximation_scale;
double m_distance_tolerance_square;
double m_angle_tolerance;
double m_cusp_limit;
unsigned m_count;
pod_bvector<point_d> m_points;
};
//-----------------------------------------------------------------curve3
class curve3
{
public:
curve3() : m_approximation_method(curve_div) {}
curve3(double x1, double y1,
double x2, double y2,
double x3, double y3) :
m_approximation_method(curve_div)
{
init(x1, y1, x2, y2, x3, y3);
}
void reset()
{
m_curve_inc.reset();
m_curve_div.reset();
}
void init(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
if(m_approximation_method == curve_inc)
{
m_curve_inc.init(x1, y1, x2, y2, x3, y3);
}
else
{
m_curve_div.init(x1, y1, x2, y2, x3, y3);
}
}
void approximation_method(curve_approximation_method_e v)
{
m_approximation_method = v;
}
curve_approximation_method_e approximation_method() const
{
return m_approximation_method;
}
void approximation_scale(double s)
{
m_curve_inc.approximation_scale(s);
m_curve_div.approximation_scale(s);
}
double approximation_scale() const
{
return m_curve_inc.approximation_scale();
}
void angle_tolerance(double a)
{
m_curve_div.angle_tolerance(a);
}
double angle_tolerance() const
{
return m_curve_div.angle_tolerance();
}
void cusp_limit(double v)
{
m_curve_div.cusp_limit(v);
}
double cusp_limit() const
{
return m_curve_div.cusp_limit();
}
void rewind(unsigned path_id)
{
if(m_approximation_method == curve_inc)
{
m_curve_inc.rewind(path_id);
}
else
{
m_curve_div.rewind(path_id);
}
}
unsigned vertex(double* x, double* y)
{
if(m_approximation_method == curve_inc)
{
return m_curve_inc.vertex(x, y);
}
return m_curve_div.vertex(x, y);
}
private:
curve3_inc m_curve_inc;
curve3_div m_curve_div;
curve_approximation_method_e m_approximation_method;
};
//-----------------------------------------------------------------curve4
class curve4
{
public:
curve4() : m_approximation_method(curve_div) {}
curve4(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4) :
m_approximation_method(curve_div)
{
init(x1, y1, x2, y2, x3, y3, x4, y4);
}
curve4(const curve4_points& cp) :
m_approximation_method(curve_div)
{
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
}
void reset()
{
m_curve_inc.reset();
m_curve_div.reset();
}
void init(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
if(m_approximation_method == curve_inc)
{
m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4);
}
else
{
m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4);
}
}
void init(const curve4_points& cp)
{
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
}
void approximation_method(curve_approximation_method_e v)
{
m_approximation_method = v;
}
curve_approximation_method_e approximation_method() const
{
return m_approximation_method;
}
void approximation_scale(double s)
{
m_curve_inc.approximation_scale(s);
m_curve_div.approximation_scale(s);
}
double approximation_scale() const { return m_curve_inc.approximation_scale(); }
void angle_tolerance(double v)
{
m_curve_div.angle_tolerance(v);
}
double angle_tolerance() const
{
return m_curve_div.angle_tolerance();
}
void cusp_limit(double v)
{
m_curve_div.cusp_limit(v);
}
double cusp_limit() const
{
return m_curve_div.cusp_limit();
}
void rewind(unsigned path_id)
{
if(m_approximation_method == curve_inc)
{
m_curve_inc.rewind(path_id);
}
else
{
m_curve_div.rewind(path_id);
}
}
unsigned vertex(double* x, double* y)
{
if(m_approximation_method == curve_inc)
{
return m_curve_inc.vertex(x, y);
}
return m_curve_div.vertex(x, y);
}
private:
curve4_inc m_curve_inc;
curve4_div m_curve_div;
curve_approximation_method_e m_approximation_method;
};
}
#endif

View File

@@ -0,0 +1,290 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// classes dda_line_interpolator, dda2_line_interpolator
//
//----------------------------------------------------------------------------
#ifndef AGG_DDA_LINE_INCLUDED
#define AGG_DDA_LINE_INCLUDED
#include <cstdlib>
#include "agg_basics.h"
namespace agg
{
//===================================================dda_line_interpolator
template<int FractionShift, int YShift=0> class dda_line_interpolator
{
public:
//--------------------------------------------------------------------
dda_line_interpolator() {}
//--------------------------------------------------------------------
dda_line_interpolator(int y1, int y2, unsigned count) :
m_y(y1),
m_inc(((y2 - y1) << FractionShift) / int(count)),
m_dy(0)
{
}
//--------------------------------------------------------------------
void operator ++ ()
{
m_dy += m_inc;
}
//--------------------------------------------------------------------
void operator -- ()
{
m_dy -= m_inc;
}
//--------------------------------------------------------------------
void operator += (unsigned n)
{
m_dy += m_inc * n;
}
//--------------------------------------------------------------------
void operator -= (unsigned n)
{
m_dy -= m_inc * n;
}
//--------------------------------------------------------------------
int y() const { return m_y + (m_dy >> (FractionShift-YShift)); }
int dy() const { return m_dy; }
private:
int m_y;
int m_inc;
int m_dy;
};
//=================================================dda2_line_interpolator
class dda2_line_interpolator
{
public:
typedef int save_data_type;
enum save_size_e { save_size = 2 };
//--------------------------------------------------------------------
dda2_line_interpolator() {}
//-------------------------------------------- Forward-adjusted line
dda2_line_interpolator(int y1, int y2, int count) :
m_cnt(count <= 0 ? 1 : count),
m_lft((y2 - y1) / m_cnt),
m_rem((y2 - y1) % m_cnt),
m_mod(m_rem),
m_y(y1)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
m_mod -= count;
}
//-------------------------------------------- Backward-adjusted line
dda2_line_interpolator(int y1, int y2, int count, int) :
m_cnt(count <= 0 ? 1 : count),
m_lft((y2 - y1) / m_cnt),
m_rem((y2 - y1) % m_cnt),
m_mod(m_rem),
m_y(y1)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
}
//-------------------------------------------- Backward-adjusted line
dda2_line_interpolator(int y, int count) :
m_cnt(count <= 0 ? 1 : count),
m_lft(y / m_cnt),
m_rem(y % m_cnt),
m_mod(m_rem),
m_y(0)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
}
//--------------------------------------------------------------------
void save(save_data_type* data) const
{
data[0] = m_mod;
data[1] = m_y;
}
//--------------------------------------------------------------------
void load(const save_data_type* data)
{
m_mod = data[0];
m_y = data[1];
}
//--------------------------------------------------------------------
void operator++()
{
m_mod += m_rem;
m_y += m_lft;
if(m_mod > 0)
{
m_mod -= m_cnt;
m_y++;
}
}
//--------------------------------------------------------------------
void operator--()
{
if(m_mod <= m_rem)
{
m_mod += m_cnt;
m_y--;
}
m_mod -= m_rem;
m_y -= m_lft;
}
//--------------------------------------------------------------------
void adjust_forward()
{
m_mod -= m_cnt;
}
//--------------------------------------------------------------------
void adjust_backward()
{
m_mod += m_cnt;
}
//--------------------------------------------------------------------
int mod() const { return m_mod; }
int rem() const { return m_rem; }
int lft() const { return m_lft; }
//--------------------------------------------------------------------
int y() const { return m_y; }
private:
int m_cnt;
int m_lft;
int m_rem;
int m_mod;
int m_y;
};
//---------------------------------------------line_bresenham_interpolator
class line_bresenham_interpolator
{
public:
enum subpixel_scale_e
{
subpixel_shift = 8,
subpixel_scale = 1 << subpixel_shift,
subpixel_mask = subpixel_scale - 1
};
//--------------------------------------------------------------------
static int line_lr(int v) { return v >> subpixel_shift; }
//--------------------------------------------------------------------
line_bresenham_interpolator(int x1, int y1, int x2, int y2) :
m_x1_lr(line_lr(x1)),
m_y1_lr(line_lr(y1)),
m_x2_lr(line_lr(x2)),
m_y2_lr(line_lr(y2)),
m_ver(std::abs(m_x2_lr - m_x1_lr) < std::abs(m_y2_lr - m_y1_lr)),
m_len(m_ver ? std::abs(m_y2_lr - m_y1_lr) :
std::abs(m_x2_lr - m_x1_lr)),
m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)),
m_interpolator(m_ver ? x1 : y1,
m_ver ? x2 : y2,
m_len)
{
}
//--------------------------------------------------------------------
bool is_ver() const { return m_ver; }
unsigned len() const { return m_len; }
int inc() const { return m_inc; }
//--------------------------------------------------------------------
void hstep()
{
++m_interpolator;
m_x1_lr += m_inc;
}
//--------------------------------------------------------------------
void vstep()
{
++m_interpolator;
m_y1_lr += m_inc;
}
//--------------------------------------------------------------------
int x1() const { return m_x1_lr; }
int y1() const { return m_y1_lr; }
int x2() const { return line_lr(m_interpolator.y()); }
int y2() const { return line_lr(m_interpolator.y()); }
int x2_hr() const { return m_interpolator.y(); }
int y2_hr() const { return m_interpolator.y(); }
private:
int m_x1_lr;
int m_y1_lr;
int m_x2_lr;
int m_y2_lr;
bool m_ver;
unsigned m_len;
int m_inc;
dda2_line_interpolator m_interpolator;
};
}
#endif

View File

@@ -0,0 +1,123 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class ellipse
//
//----------------------------------------------------------------------------
#ifndef AGG_ELLIPSE_INCLUDED
#define AGG_ELLIPSE_INCLUDED
#include "agg_basics.h"
#include <cmath>
namespace agg
{
//----------------------------------------------------------------ellipse
class ellipse
{
public:
ellipse() :
m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0),
m_num(4), m_step(0), m_cw(false) {}
ellipse(double x, double y, double rx, double ry,
unsigned num_steps=0, bool cw=false) :
m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0),
m_num(num_steps), m_step(0), m_cw(cw)
{
if(m_num == 0) calc_num_steps();
}
void init(double x, double y, double rx, double ry,
unsigned num_steps=0, bool cw=false);
void approximation_scale(double scale);
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
void calc_num_steps();
double m_x;
double m_y;
double m_rx;
double m_ry;
double m_scale;
unsigned m_num;
unsigned m_step;
bool m_cw;
};
//------------------------------------------------------------------------
inline void ellipse::init(double x, double y, double rx, double ry,
unsigned num_steps, bool cw)
{
m_x = x;
m_y = y;
m_rx = rx;
m_ry = ry;
m_num = num_steps;
m_step = 0;
m_cw = cw;
if(m_num == 0) calc_num_steps();
}
//------------------------------------------------------------------------
inline void ellipse::approximation_scale(double scale)
{
m_scale = scale;
calc_num_steps();
}
//------------------------------------------------------------------------
inline void ellipse::calc_num_steps()
{
double ra = (std::fabs(m_rx) + std::fabs(m_ry)) / 2;
double da = std::acos(ra / (ra + 0.125 / m_scale)) * 2;
m_num = uround(2*pi / da);
}
//------------------------------------------------------------------------
inline void ellipse::rewind(unsigned)
{
m_step = 0;
}
//------------------------------------------------------------------------
inline unsigned ellipse::vertex(double* x, double* y)
{
if(m_step == m_num)
{
++m_step;
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
}
if(m_step > m_num) return path_cmd_stop;
double angle = double(m_step) / double(m_num) * 2.0 * pi;
if(m_cw) angle = 2.0 * pi - angle;
*x = m_x + std::cos(angle) * m_rx;
*y = m_y + std::sin(angle) * m_ry;
m_step++;
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
}
}
#endif

View File

@@ -0,0 +1,113 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Simple Bresenham interpolator for ellipsees
//
//----------------------------------------------------------------------------
#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED
#define AGG_ELLIPSE_BRESENHAM_INCLUDED
#include "agg_basics.h"
namespace agg
{
//------------------------------------------ellipse_bresenham_interpolator
class ellipse_bresenham_interpolator
{
public:
ellipse_bresenham_interpolator(int rx, int ry) :
m_rx2(rx * rx),
m_ry2(ry * ry),
m_two_rx2(m_rx2 << 1),
m_two_ry2(m_ry2 << 1),
m_dx(0),
m_dy(0),
m_inc_x(0),
m_inc_y(-ry * m_two_rx2),
m_cur_f(0)
{}
int dx() const { return m_dx; }
int dy() const { return m_dy; }
void operator++ ()
{
int mx, my, mxy, min_m;
int fx, fy, fxy;
mx = fx = m_cur_f + m_inc_x + m_ry2;
if(mx < 0) mx = -mx;
my = fy = m_cur_f + m_inc_y + m_rx2;
if(my < 0) my = -my;
mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2;
if(mxy < 0) mxy = -mxy;
min_m = mx;
bool flag = true;
if(min_m > my)
{
min_m = my;
flag = false;
}
m_dx = m_dy = 0;
if(min_m > mxy)
{
m_inc_x += m_two_ry2;
m_inc_y += m_two_rx2;
m_cur_f = fxy;
m_dx = 1;
m_dy = 1;
return;
}
if(flag)
{
m_inc_x += m_two_ry2;
m_cur_f = fx;
m_dx = 1;
return;
}
m_inc_y += m_two_rx2;
m_cur_f = fy;
m_dy = 1;
}
private:
int m_rx2;
int m_ry2;
int m_two_rx2;
int m_two_ry2;
int m_dx;
int m_dy;
int m_inc_x;
int m_inc_y;
int m_cur_f;
};
}
#endif

View File

@@ -0,0 +1,59 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_EMBEDDED_RASTER_FONTS_INCLUDED
#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED
#include "agg_basics.h"
namespace agg
{
extern const int8u gse4x6[];
extern const int8u gse4x8[];
extern const int8u gse5x7[];
extern const int8u gse5x9[];
extern const int8u gse6x12[];
extern const int8u gse6x9[];
extern const int8u gse7x11[];
extern const int8u gse7x11_bold[];
extern const int8u gse7x15[];
extern const int8u gse7x15_bold[];
extern const int8u gse8x16[];
extern const int8u gse8x16_bold[];
extern const int8u mcs11_prop[];
extern const int8u mcs11_prop_condensed[];
extern const int8u mcs12_prop[];
extern const int8u mcs13_prop[];
extern const int8u mcs5x10_mono[];
extern const int8u mcs5x11_mono[];
extern const int8u mcs6x10_mono[];
extern const int8u mcs6x11_mono[];
extern const int8u mcs7x12_mono_high[];
extern const int8u mcs7x12_mono_low[];
extern const int8u verdana12[];
extern const int8u verdana12_bold[];
extern const int8u verdana13[];
extern const int8u verdana13_bold[];
extern const int8u verdana14[];
extern const int8u verdana14_bold[];
extern const int8u verdana16[];
extern const int8u verdana16_bold[];
extern const int8u verdana17[];
extern const int8u verdana17_bold[];
extern const int8u verdana18[];
extern const int8u verdana18_bold[];
}
#endif

View File

@@ -0,0 +1,409 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
#define AGG_FONT_CACHE_MANAGER_INCLUDED
#include <cstring>
#include "agg_array.h"
namespace agg
{
//---------------------------------------------------------glyph_data_type
enum glyph_data_type
{
glyph_data_invalid = 0,
glyph_data_mono = 1,
glyph_data_gray8 = 2,
glyph_data_outline = 3
};
//-------------------------------------------------------------glyph_cache
struct glyph_cache
{
unsigned glyph_index;
int8u* data;
unsigned data_size;
glyph_data_type data_type;
rect_i bounds;
double advance_x;
double advance_y;
};
//--------------------------------------------------------------font_cache
class font_cache
{
public:
enum block_size_e { block_size = 16384-16 };
//--------------------------------------------------------------------
font_cache() :
m_allocator(block_size),
m_font_signature(0)
{}
//--------------------------------------------------------------------
void signature(const char* font_signature)
{
m_font_signature = (char*)m_allocator.allocate(std::strlen(font_signature) + 1);
std::strcpy(m_font_signature, font_signature);
std::memset(m_glyphs, 0, sizeof(m_glyphs));
}
//--------------------------------------------------------------------
bool font_is(const char* font_signature) const
{
return std::strcmp(font_signature, m_font_signature) == 0;
}
//--------------------------------------------------------------------
const glyph_cache* find_glyph(unsigned glyph_code) const
{
unsigned msb = (glyph_code >> 8) & 0xFF;
if(m_glyphs[msb])
{
return m_glyphs[msb][glyph_code & 0xFF];
}
return 0;
}
//--------------------------------------------------------------------
glyph_cache* cache_glyph(unsigned glyph_code,
unsigned glyph_index,
unsigned data_size,
glyph_data_type data_type,
const rect_i& bounds,
double advance_x,
double advance_y)
{
unsigned msb = (glyph_code >> 8) & 0xFF;
if(m_glyphs[msb] == 0)
{
m_glyphs[msb] =
(glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
sizeof(glyph_cache*));
std::memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
}
unsigned lsb = glyph_code & 0xFF;
if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
glyph_cache* glyph =
(glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
sizeof(double));
glyph->glyph_index = glyph_index;
glyph->data = m_allocator.allocate(data_size);
glyph->data_size = data_size;
glyph->data_type = data_type;
glyph->bounds = bounds;
glyph->advance_x = advance_x;
glyph->advance_y = advance_y;
return m_glyphs[msb][lsb] = glyph;
}
private:
block_allocator m_allocator;
glyph_cache** m_glyphs[256];
char* m_font_signature;
};
//---------------------------------------------------------font_cache_pool
class font_cache_pool
{
public:
//--------------------------------------------------------------------
~font_cache_pool()
{
unsigned i;
for(i = 0; i < m_num_fonts; ++i)
{
obj_allocator<font_cache>::deallocate(m_fonts[i]);
}
pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
}
//--------------------------------------------------------------------
font_cache_pool(unsigned max_fonts=32) :
m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)),
m_max_fonts(max_fonts),
m_num_fonts(0),
m_cur_font(0)
{}
//--------------------------------------------------------------------
void font(const char* font_signature, bool reset_cache = false)
{
int idx = find_font(font_signature);
if(idx >= 0)
{
if(reset_cache)
{
obj_allocator<font_cache>::deallocate(m_fonts[idx]);
m_fonts[idx] = obj_allocator<font_cache>::allocate();
m_fonts[idx]->signature(font_signature);
}
m_cur_font = m_fonts[idx];
}
else
{
if(m_num_fonts >= m_max_fonts)
{
obj_allocator<font_cache>::deallocate(m_fonts[0]);
std::memcpy(m_fonts,
m_fonts + 1,
(m_max_fonts - 1) * sizeof(font_cache*));
m_num_fonts = m_max_fonts - 1;
}
m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
m_fonts[m_num_fonts]->signature(font_signature);
m_cur_font = m_fonts[m_num_fonts];
++m_num_fonts;
}
}
//--------------------------------------------------------------------
const font_cache* font() const
{
return m_cur_font;
}
//--------------------------------------------------------------------
const glyph_cache* find_glyph(unsigned glyph_code) const
{
if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
return 0;
}
//--------------------------------------------------------------------
glyph_cache* cache_glyph(unsigned glyph_code,
unsigned glyph_index,
unsigned data_size,
glyph_data_type data_type,
const rect_i& bounds,
double advance_x,
double advance_y)
{
if(m_cur_font)
{
return m_cur_font->cache_glyph(glyph_code,
glyph_index,
data_size,
data_type,
bounds,
advance_x,
advance_y);
}
return 0;
}
//--------------------------------------------------------------------
int find_font(const char* font_signature)
{
unsigned i;
for(i = 0; i < m_num_fonts; i++)
{
if(m_fonts[i]->font_is(font_signature)) return int(i);
}
return -1;
}
private:
font_cache** m_fonts;
unsigned m_max_fonts;
unsigned m_num_fonts;
font_cache* m_cur_font;
};
//------------------------------------------------------------------------
enum glyph_rendering
{
glyph_ren_native_mono,
glyph_ren_native_gray8,
glyph_ren_outline,
glyph_ren_agg_mono,
glyph_ren_agg_gray8
};
//------------------------------------------------------font_cache_manager
template<class FontEngine> class font_cache_manager
{
public:
typedef FontEngine font_engine_type;
typedef font_cache_manager<FontEngine> self_type;
typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
//--------------------------------------------------------------------
font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
m_fonts(max_fonts),
m_engine(engine),
m_change_stamp(-1),
m_prev_glyph(0),
m_last_glyph(0)
{}
//--------------------------------------------------------------------
void reset_last_glyph()
{
m_prev_glyph = m_last_glyph = 0;
}
//--------------------------------------------------------------------
const glyph_cache* glyph(unsigned glyph_code)
{
synchronize();
const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
if(gl)
{
m_prev_glyph = m_last_glyph;
return m_last_glyph = gl;
}
else
{
if(m_engine.prepare_glyph(glyph_code))
{
m_prev_glyph = m_last_glyph;
m_last_glyph = m_fonts.cache_glyph(glyph_code,
m_engine.glyph_index(),
m_engine.data_size(),
m_engine.data_type(),
m_engine.bounds(),
m_engine.advance_x(),
m_engine.advance_y());
m_engine.write_glyph_to(m_last_glyph->data);
return m_last_glyph;
}
}
return 0;
}
//--------------------------------------------------------------------
void init_embedded_adaptors(const glyph_cache* gl,
double x, double y,
double scale=1.0)
{
if(gl)
{
switch(gl->data_type)
{
default: return;
case glyph_data_mono:
m_mono_adaptor.init(gl->data, gl->data_size, x, y);
break;
case glyph_data_gray8:
m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
break;
case glyph_data_outline:
m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
break;
}
}
}
//--------------------------------------------------------------------
path_adaptor_type& path_adaptor() { return m_path_adaptor; }
gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
mono_scanline_type& mono_scanline() { return m_mono_scanline; }
//--------------------------------------------------------------------
const glyph_cache* perv_glyph() const { return m_prev_glyph; }
const glyph_cache* last_glyph() const { return m_last_glyph; }
//--------------------------------------------------------------------
bool add_kerning(double* x, double* y)
{
if(m_prev_glyph && m_last_glyph)
{
return m_engine.add_kerning(m_prev_glyph->glyph_index,
m_last_glyph->glyph_index,
x, y);
}
return false;
}
//--------------------------------------------------------------------
void precache(unsigned from, unsigned to)
{
for(; from <= to; ++from) glyph(from);
}
//--------------------------------------------------------------------
void reset_cache()
{
m_fonts.font(m_engine.font_signature(), true);
m_change_stamp = m_engine.change_stamp();
m_prev_glyph = m_last_glyph = 0;
}
private:
//--------------------------------------------------------------------
font_cache_manager(const self_type&);
const self_type& operator = (const self_type&);
//--------------------------------------------------------------------
void synchronize()
{
if(m_change_stamp != m_engine.change_stamp())
{
m_fonts.font(m_engine.font_signature());
m_change_stamp = m_engine.change_stamp();
m_prev_glyph = m_last_glyph = 0;
}
}
font_cache_pool m_fonts;
font_engine_type& m_engine;
int m_change_stamp;
double m_dx;
double m_dy;
const glyph_cache* m_prev_glyph;
const glyph_cache* m_last_glyph;
path_adaptor_type m_path_adaptor;
gray8_adaptor_type m_gray8_adaptor;
gray8_scanline_type m_gray8_scanline;
mono_adaptor_type m_mono_adaptor;
mono_scanline_type m_mono_scanline;
};
}
#endif

View File

@@ -0,0 +1,311 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_FONT_CACHE_MANAGER2_INCLUDED
#define AGG_FONT_CACHE_MANAGER2_INCLUDED
#include <cassert>
#include <exception>
#include <cstring>
#include "agg_array.h"
namespace agg {
namespace fman {
//---------------------------------------------------------glyph_data_type
enum glyph_data_type
{
glyph_data_invalid = 0,
glyph_data_mono = 1,
glyph_data_gray8 = 2,
glyph_data_outline = 3
};
//-------------------------------------------------------------cached_glyph
struct cached_glyph
{
void * cached_font;
unsigned glyph_code;
unsigned glyph_index;
int8u* data;
unsigned data_size;
glyph_data_type data_type;
rect_i bounds;
double advance_x;
double advance_y;
};
//--------------------------------------------------------------cached_glyphs
class cached_glyphs
{
public:
enum block_size_e { block_size = 16384-16 };
//--------------------------------------------------------------------
cached_glyphs()
: m_allocator(block_size)
{ std::memset(m_glyphs, 0, sizeof(m_glyphs)); }
//--------------------------------------------------------------------
const cached_glyph* find_glyph(unsigned glyph_code) const
{
unsigned msb = (glyph_code >> 8) & 0xFF;
if(m_glyphs[msb])
{
return m_glyphs[msb][glyph_code & 0xFF];
}
return 0;
}
//--------------------------------------------------------------------
cached_glyph* cache_glyph(
void * cached_font,
unsigned glyph_code,
unsigned glyph_index,
unsigned data_size,
glyph_data_type data_type,
const rect_i& bounds,
double advance_x,
double advance_y)
{
unsigned msb = (glyph_code >> 8) & 0xFF;
if(m_glyphs[msb] == 0)
{
m_glyphs[msb] =
(cached_glyph**)m_allocator.allocate(sizeof(cached_glyph*) * 256,
sizeof(cached_glyph*));
std::memset(m_glyphs[msb], 0, sizeof(cached_glyph*) * 256);
}
unsigned lsb = glyph_code & 0xFF;
if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
cached_glyph* glyph =
(cached_glyph*)m_allocator.allocate(sizeof(cached_glyph),
sizeof(double));
glyph->cached_font = cached_font;
glyph->glyph_code = glyph_code;
glyph->glyph_index = glyph_index;
glyph->data = m_allocator.allocate(data_size);
glyph->data_size = data_size;
glyph->data_type = data_type;
glyph->bounds = bounds;
glyph->advance_x = advance_x;
glyph->advance_y = advance_y;
return m_glyphs[msb][lsb] = glyph;
}
private:
block_allocator m_allocator;
cached_glyph** m_glyphs[256];
};
//------------------------------------------------------------------------
enum glyph_rendering
{
glyph_ren_native_mono,
glyph_ren_native_gray8,
glyph_ren_outline,
glyph_ren_agg_mono,
glyph_ren_agg_gray8
};
//------------------------------------------------------font_cache_manager
template<class FontEngine> class font_cache_manager
{
public:
typedef FontEngine font_engine_type;
typedef font_cache_manager<FontEngine> self_type;
typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
struct cached_font
{
cached_font(
font_engine_type& engine,
typename FontEngine::loaded_face *face,
double height,
double width,
bool hinting,
glyph_rendering rendering )
: m_engine( engine )
, m_face( face )
, m_height( height )
, m_width( width )
, m_hinting( hinting )
, m_rendering( rendering )
{
select_face();
m_face_height=m_face->height();
m_face_width=m_face->width();
m_face_ascent=m_face->ascent();
m_face_descent=m_face->descent();
m_face_ascent_b=m_face->ascent_b();
m_face_descent_b=m_face->descent_b();
}
double height() const
{
return m_face_height;
}
double width() const
{
return m_face_width;
}
double ascent() const
{
return m_face_ascent;
}
double descent() const
{
return m_face_descent;
}
double ascent_b() const
{
return m_face_ascent_b;
}
double descent_b() const
{
return m_face_descent_b;
}
bool add_kerning( const cached_glyph *first, const cached_glyph *second, double* x, double* y)
{
if( !first || !second )
return false;
select_face();
return m_face->add_kerning(
first->glyph_index, second->glyph_index, x, y );
}
void select_face()
{
m_face->select_instance( m_height, m_width, m_hinting, m_rendering );
}
const cached_glyph *get_glyph(unsigned cp)
{
const cached_glyph *glyph=m_glyphs.find_glyph(cp);
if( glyph==0 )
{
typename FontEngine::prepared_glyph prepared;
select_face();
bool success=m_face->prepare_glyph(cp, &prepared);
if( success )
{
glyph=m_glyphs.cache_glyph(
this,
prepared.glyph_code,
prepared.glyph_index,
prepared.data_size,
prepared.data_type,
prepared.bounds,
prepared.advance_x,
prepared.advance_y );
assert( glyph!=0 );
m_face->write_glyph_to(&prepared,glyph->data);
}
}
return glyph;
}
font_engine_type& m_engine;
typename FontEngine::loaded_face *m_face;
double m_height;
double m_width;
bool m_hinting;
glyph_rendering m_rendering;
double m_face_height;
double m_face_width;
double m_face_ascent;
double m_face_descent;
double m_face_ascent_b;
double m_face_descent_b;
cached_glyphs m_glyphs;
};
//--------------------------------------------------------------------
font_cache_manager(font_engine_type& engine, unsigned max_fonts=32)
:m_engine(engine)
{ }
//--------------------------------------------------------------------
void init_embedded_adaptors(const cached_glyph* gl,
double x, double y,
double scale=1.0)
{
if(gl)
{
switch(gl->data_type)
{
default: return;
case glyph_data_mono:
m_mono_adaptor.init(gl->data, gl->data_size, x, y);
break;
case glyph_data_gray8:
m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
break;
case glyph_data_outline:
m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
break;
}
}
}
//--------------------------------------------------------------------
path_adaptor_type& path_adaptor() { return m_path_adaptor; }
gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
mono_scanline_type& mono_scanline() { return m_mono_scanline; }
private:
//--------------------------------------------------------------------
font_cache_manager(const self_type&);
const self_type& operator = (const self_type&);
font_engine_type& m_engine;
path_adaptor_type m_path_adaptor;
gray8_adaptor_type m_gray8_adaptor;
gray8_scanline_type m_gray8_scanline;
mono_adaptor_type m_mono_adaptor;
mono_scanline_type m_mono_scanline;
};
}
}
#endif

View File

@@ -0,0 +1,131 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED
#define AGG_GAMMA_FUNCTIONS_INCLUDED
#include "agg_basics.h"
namespace agg
{
//===============================================================gamma_none
struct gamma_none
{
double operator()(double x) const { return x; }
};
//==============================================================gamma_power
class gamma_power
{
public:
gamma_power() : m_gamma(1.0) {}
gamma_power(double g) : m_gamma(g) {}
void gamma(double g) { m_gamma = g; }
double gamma() const { return m_gamma; }
double operator() (double x) const
{
return pow(x, m_gamma);
}
private:
double m_gamma;
};
//==========================================================gamma_threshold
class gamma_threshold
{
public:
gamma_threshold() : m_threshold(0.5) {}
gamma_threshold(double t) : m_threshold(t) {}
void threshold(double t) { m_threshold = t; }
double threshold() const { return m_threshold; }
double operator() (double x) const
{
return (x < m_threshold) ? 0.0 : 1.0;
}
private:
double m_threshold;
};
//============================================================gamma_linear
class gamma_linear
{
public:
gamma_linear() : m_start(0.0), m_end(1.0) {}
gamma_linear(double s, double e) : m_start(s), m_end(e) {}
void set(double s, double e) { m_start = s; m_end = e; }
void start(double s) { m_start = s; }
void end(double e) { m_end = e; }
double start() const { return m_start; }
double end() const { return m_end; }
double operator() (double x) const
{
if(x < m_start) return 0.0;
if(x > m_end) return 1.0;
return (x - m_start) / (m_end - m_start);
}
private:
double m_start;
double m_end;
};
//==========================================================gamma_multiply
class gamma_multiply
{
public:
gamma_multiply() : m_mul(1.0) {}
gamma_multiply(double v) : m_mul(v) {}
void value(double v) { m_mul = v; }
double value() const { return m_mul; }
double operator() (double x) const
{
double y = x * m_mul;
if(y > 1.0) y = 1.0;
return y;
}
private:
double m_mul;
};
inline double sRGB_to_linear(double x)
{
return (x <= 0.04045) ? (x / 12.92) : pow((x + 0.055) / (1.055), 2.4);
}
inline double linear_to_sRGB(double x)
{
return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 1 / 2.4) - 0.055);
}
}
#endif

View File

@@ -0,0 +1,307 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GAMMA_LUT_INCLUDED
#define AGG_GAMMA_LUT_INCLUDED
#include <cmath>
#include "agg_basics.h"
#include "agg_gamma_functions.h"
namespace agg
{
template<class LoResT=int8u,
class HiResT=int8u,
unsigned GammaShift=8,
unsigned HiResShift=8> class gamma_lut
{
public:
typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type;
enum gamma_scale_e
{
gamma_shift = GammaShift,
gamma_size = 1 << gamma_shift,
gamma_mask = gamma_size - 1
};
enum hi_res_scale_e
{
hi_res_shift = HiResShift,
hi_res_size = 1 << hi_res_shift,
hi_res_mask = hi_res_size - 1
};
~gamma_lut()
{
pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
}
gamma_lut() :
m_gamma(1.0),
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
{
unsigned i;
for(i = 0; i < gamma_size; i++)
{
m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
}
for(i = 0; i < hi_res_size; i++)
{
m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
}
}
gamma_lut(double g) :
m_gamma(1.0),
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
{
gamma(g);
}
void gamma(double g)
{
m_gamma = g;
unsigned i;
for(i = 0; i < gamma_size; i++)
{
m_dir_gamma[i] = (HiResT)
uround(std::pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask));
}
double inv_g = 1.0 / g;
for(i = 0; i < hi_res_size; i++)
{
m_inv_gamma[i] = (LoResT)
uround(std::pow(i / double(hi_res_mask), inv_g) * double(gamma_mask));
}
}
double gamma() const
{
return m_gamma;
}
HiResT dir(LoResT v) const
{
return m_dir_gamma[unsigned(v)];
}
LoResT inv(HiResT v) const
{
return m_inv_gamma[unsigned(v)];
}
private:
gamma_lut(const self_type&);
const self_type& operator = (const self_type&);
double m_gamma;
HiResT* m_dir_gamma;
LoResT* m_inv_gamma;
};
//
// sRGB support classes
//
// Optimized sRGB lookup table. The direct conversion (sRGB to linear)
// is a straightforward lookup. The inverse conversion (linear to sRGB)
// is implemented using binary search.
template<class LinearType>
class sRGB_lut_base
{
public:
LinearType dir(int8u v) const
{
return m_dir_table[v];
}
int8u inv(LinearType v) const
{
// Unrolled binary search.
int8u x = 0;
if (v > m_inv_table[128]) x = 128;
if (v > m_inv_table[x + 64]) x += 64;
if (v > m_inv_table[x + 32]) x += 32;
if (v > m_inv_table[x + 16]) x += 16;
if (v > m_inv_table[x + 8]) x += 8;
if (v > m_inv_table[x + 4]) x += 4;
if (v > m_inv_table[x + 2]) x += 2;
if (v > m_inv_table[x + 1]) x += 1;
return x;
}
protected:
LinearType m_dir_table[256];
LinearType m_inv_table[256];
// Only derived classes may instantiate.
sRGB_lut_base()
{
}
};
// sRGB_lut - implements sRGB conversion for the various types.
// Base template is undefined, specializations are provided below.
template<class LinearType>
class sRGB_lut;
template<>
class sRGB_lut<float> : public sRGB_lut_base<float>
{
public:
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
// Floating-point RGB is in range [0,1].
m_dir_table[i] = float(sRGB_to_linear(i / 255.0));
m_inv_table[i] = float(sRGB_to_linear((i - 0.5) / 255.0));
}
}
};
template<>
class sRGB_lut<int16u> : public sRGB_lut_base<int16u>
{
public:
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (int i = 1; i <= 255; ++i)
{
// 16-bit RGB is in range [0,65535].
m_dir_table[i] = uround(65535.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(65535.0 * sRGB_to_linear((i - 0.5) / 255.0));
}
}
};
template<>
class sRGB_lut<int8u> : public sRGB_lut_base<int8u>
{
public:
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (int i = 1; i <= 255; ++i)
{
// 8-bit RGB is handled with simple bidirectional lookup tables.
m_dir_table[i] = uround(255.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 255.0));
}
}
int8u inv(int8u v) const
{
// In this case, the inverse transform is a simple lookup.
return m_inv_table[v];
}
};
// Common base class for sRGB_conv objects. Defines an internal
// sRGB_lut object so that users don't have to.
template<class T>
class sRGB_conv_base
{
public:
static T rgb_from_sRGB(int8u x)
{
return lut.dir(x);
}
static int8u rgb_to_sRGB(T x)
{
return lut.inv(x);
}
private:
static sRGB_lut<T> lut;
};
// Definition of sRGB_conv_base::lut. Due to the fact that this a template,
// we don't need to place the definition in a cpp file. Hurrah.
template<class T>
sRGB_lut<T> sRGB_conv_base<T>::lut;
// Wrapper for sRGB-linear conversion.
// Base template is undefined, specializations are provided below.
template<class T>
class sRGB_conv;
template<>
class sRGB_conv<float> : public sRGB_conv_base<float>
{
public:
static float alpha_from_sRGB(int8u x)
{
static const double y = 1 / 255.0;
return float(x * y);
}
static int8u alpha_to_sRGB(float x)
{
if (x < 0) return 0;
if (x > 1) return 255;
return int8u(0.5 + x * 255);
}
};
template<>
class sRGB_conv<int16u> : public sRGB_conv_base<int16u>
{
public:
static int16u alpha_from_sRGB(int8u x)
{
return (x << 8) | x;
}
static int8u alpha_to_sRGB(int16u x)
{
return x >> 8;
}
};
template<>
class sRGB_conv<int8u> : public sRGB_conv_base<int8u>
{
public:
static int8u alpha_from_sRGB(int8u x)
{
return x;
}
static int8u alpha_to_sRGB(int8u x)
{
return x;
}
};
}
#endif

View File

@@ -0,0 +1,155 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GLYPH_RASTER_BIN_INCLUDED
#define AGG_GLYPH_RASTER_BIN_INCLUDED
#include <cstring>
#include "agg_basics.h"
namespace agg
{
//========================================================glyph_raster_bin
template<class ColorT> class glyph_raster_bin
{
public:
typedef ColorT color_type;
//--------------------------------------------------------------------
struct glyph_rect
{
int x1,y1,x2,y2;
double dx, dy;
};
//--------------------------------------------------------------------
glyph_raster_bin(const int8u* font) :
m_font(font),
m_big_endian(false)
{
int t = 1;
if(*(char*)&t == 0) m_big_endian = true;
std::memset(m_span, 0, sizeof(m_span));
}
//--------------------------------------------------------------------
const int8u* font() const { return m_font; }
void font(const int8u* f) { m_font = f; }
//--------------------------------------------------------------------
double height() const { return m_font[0]; }
double base_line() const { return m_font[1]; }
//--------------------------------------------------------------------
template<class CharT>
double width(const CharT* str) const
{
unsigned start_char = m_font[2];
unsigned num_chars = m_font[3];
unsigned w = 0;
while(*str)
{
unsigned glyph = *str;
const int8u* bits = m_font + 4 + num_chars * 2 +
value(m_font + 4 + (glyph - start_char) * 2);
w += *bits;
++str;
}
return w;
}
//--------------------------------------------------------------------
void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip)
{
unsigned start_char = m_font[2];
unsigned num_chars = m_font[3];
m_bits = m_font + 4 + num_chars * 2 +
value(m_font + 4 + (glyph - start_char) * 2);
m_glyph_width = *m_bits++;
m_glyph_byte_width = (m_glyph_width + 7) >> 3;
r->x1 = int(x);
r->x2 = r->x1 + m_glyph_width - 1;
if(flip)
{
r->y1 = int(y) - m_font[0] + m_font[1];
r->y2 = r->y1 + m_font[0] - 1;
}
else
{
r->y1 = int(y) - m_font[1] + 1;
r->y2 = r->y1 + m_font[0] - 1;
}
r->dx = m_glyph_width;
r->dy = 0;
}
//--------------------------------------------------------------------
const cover_type* span(unsigned i)
{
i = m_font[0] - i - 1;
const int8u* bits = m_bits + i * m_glyph_byte_width;
unsigned j;
unsigned val = *bits;
unsigned nb = 0;
for(j = 0; j < m_glyph_width; ++j)
{
m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none);
val <<= 1;
if(++nb >= 8)
{
val = *++bits;
nb = 0;
}
}
return m_span;
}
private:
//--------------------------------------------------------------------
int16u value(const int8u* p) const
{
int16u v;
if(m_big_endian)
{
*(int8u*)&v = p[1];
*((int8u*)&v + 1) = p[0];
}
else
{
*(int8u*)&v = p[0];
*((int8u*)&v + 1) = p[1];
}
return v;
}
//--------------------------------------------------------------------
const int8u* m_font;
bool m_big_endian;
cover_type m_span[32];
const int8u* m_bits;
unsigned m_glyph_width;
unsigned m_glyph_byte_width;
};
}
#endif

View File

@@ -0,0 +1,244 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GRADIENT_LUT_INCLUDED
#define AGG_GRADIENT_LUT_INCLUDED
#include "agg_array.h"
#include "agg_dda_line.h"
#include "agg_color_rgba.h"
#include "agg_color_gray.h"
namespace agg
{
//======================================================color_interpolator
template<class ColorT> struct color_interpolator
{
public:
typedef ColorT color_type;
color_interpolator(const color_type& c1,
const color_type& c2,
unsigned len) :
m_c1(c1),
m_c2(c2),
m_len(len),
m_count(0)
{}
void operator ++ ()
{
++m_count;
}
color_type color() const
{
return m_c1.gradient(m_c2, double(m_count) / m_len);
}
private:
color_type m_c1;
color_type m_c2;
unsigned m_len;
unsigned m_count;
};
//========================================================================
// Fast specialization for rgba8
template<> struct color_interpolator<rgba8>
{
public:
typedef rgba8 color_type;
color_interpolator(const color_type& c1,
const color_type& c2,
unsigned len) :
r(c1.r, c2.r, len),
g(c1.g, c2.g, len),
b(c1.b, c2.b, len),
a(c1.a, c2.a, len)
{}
void operator ++ ()
{
++r; ++g; ++b; ++a;
}
color_type color() const
{
return color_type(r.y(), g.y(), b.y(), a.y());
}
private:
agg::dda_line_interpolator<14> r, g, b, a;
};
//========================================================================
// Fast specialization for gray8
template<> struct color_interpolator<gray8>
{
public:
typedef gray8 color_type;
color_interpolator(const color_type& c1,
const color_type& c2,
unsigned len) :
v(c1.v, c2.v, len),
a(c1.a, c2.a, len)
{}
void operator ++ ()
{
++v; ++a;
}
color_type color() const
{
return color_type(v.y(), a.y());
}
private:
agg::dda_line_interpolator<14> v,a;
};
//============================================================gradient_lut
template<class ColorInterpolator,
unsigned ColorLutSize=256> class gradient_lut
{
public:
typedef ColorInterpolator interpolator_type;
typedef typename interpolator_type::color_type color_type;
enum { color_lut_size = ColorLutSize };
//--------------------------------------------------------------------
gradient_lut() : m_color_lut(color_lut_size) {}
// Build Gradient Lut
// First, call remove_all(), then add_color() at least twice,
// then build_lut(). Argument "offset" in add_color must be
// in range [0...1] and defines a color stop as it is described
// in SVG specification, section Gradients and Patterns.
// The simplest linear gradient is:
// gradient_lut.add_color(0.0, start_color);
// gradient_lut.add_color(1.0, end_color);
//--------------------------------------------------------------------
void remove_all();
void add_color(double offset, const color_type& color);
void build_lut();
// Size-index Interface. This class can be used directly as the
// ColorF in span_gradient. All it needs is two access methods
// size() and operator [].
//--------------------------------------------------------------------
static unsigned size()
{
return color_lut_size;
}
const color_type& operator [] (unsigned i) const
{
return m_color_lut[i];
}
private:
//--------------------------------------------------------------------
struct color_point
{
double offset;
color_type color;
color_point() {}
color_point(double off, const color_type& c) :
offset(off), color(c)
{
if(offset < 0.0) offset = 0.0;
if(offset > 1.0) offset = 1.0;
}
};
typedef agg::pod_bvector<color_point, 4> color_profile_type;
typedef agg::pod_array<color_type> color_lut_type;
static bool offset_less(const color_point& a, const color_point& b)
{
return a.offset < b.offset;
}
static bool offset_equal(const color_point& a, const color_point& b)
{
return a.offset == b.offset;
}
//--------------------------------------------------------------------
color_profile_type m_color_profile;
color_lut_type m_color_lut;
};
//------------------------------------------------------------------------
template<class T, unsigned S>
void gradient_lut<T,S>::remove_all()
{
m_color_profile.remove_all();
}
//------------------------------------------------------------------------
template<class T, unsigned S>
void gradient_lut<T,S>::add_color(double offset, const color_type& color)
{
m_color_profile.add(color_point(offset, color));
}
//------------------------------------------------------------------------
template<class T, unsigned S>
void gradient_lut<T,S>::build_lut()
{
quick_sort(m_color_profile, offset_less);
m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
if(m_color_profile.size() >= 2)
{
unsigned i;
unsigned start = uround(m_color_profile[0].offset * color_lut_size);
unsigned end;
color_type c = m_color_profile[0].color;
for(i = 0; i < start; i++)
{
m_color_lut[i] = c;
}
for(i = 1; i < m_color_profile.size(); i++)
{
end = uround(m_color_profile[i].offset * color_lut_size);
interpolator_type ci(m_color_profile[i-1].color,
m_color_profile[i ].color,
end - start + 1);
while(start < end)
{
m_color_lut[start] = ci.color();
++ci;
++start;
}
}
c = m_color_profile.last().color;
for(; end < m_color_lut.size(); end++)
{
m_color_lut[end] = c;
}
}
}
}
#endif

View File

@@ -0,0 +1,153 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Class gsv_text
//
//----------------------------------------------------------------------------
#ifndef AGG_GSV_TEXT_INCLUDED
#define AGG_GSV_TEXT_INCLUDED
#include "agg_array.h"
#include "agg_conv_stroke.h"
#include "agg_conv_transform.h"
namespace agg
{
//---------------------------------------------------------------gsv_text
//
// See Implementation agg_gsv_text.cpp
//
class gsv_text
{
enum status
{
initial,
next_char,
start_glyph,
glyph
};
public:
gsv_text();
void font(const void* font);
void flip(bool flip_y) { m_flip = flip_y; }
void load_font(const char* file);
void size(double height, double width=0.0);
void space(double space);
void line_space(double line_space);
void start_point(double x, double y);
void text(const char* text);
double text_width();
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
// not supposed to be copied
gsv_text(const gsv_text&);
const gsv_text& operator = (const gsv_text&);
int16u value(const int8u* p) const
{
int16u v;
if(m_big_endian)
{
*(int8u*)&v = p[1];
*((int8u*)&v + 1) = p[0];
}
else
{
*(int8u*)&v = p[0];
*((int8u*)&v + 1) = p[1];
}
return v;
}
private:
double m_x;
double m_y;
double m_start_x;
double m_width;
double m_height;
double m_space;
double m_line_space;
char m_chr[2];
char* m_text;
pod_array<char> m_text_buf;
char* m_cur_chr;
const void* m_font;
pod_array<char> m_loaded_font;
status m_status;
bool m_big_endian;
bool m_flip;
int8u* m_indices;
int8* m_glyphs;
int8* m_bglyph;
int8* m_eglyph;
double m_w;
double m_h;
};
//--------------------------------------------------------gsv_text_outline
template<class Transformer = trans_affine> class gsv_text_outline
{
public:
gsv_text_outline(gsv_text& text, Transformer& trans) :
m_polyline(text),
m_trans(m_polyline, trans)
{
}
void width(double w)
{
m_polyline.width(w);
}
void transformer(const Transformer* trans)
{
m_trans->transformer(trans);
}
void rewind(unsigned path_id)
{
m_trans.rewind(path_id);
m_polyline.line_join(round_join);
m_polyline.line_cap(round_cap);
}
unsigned vertex(double* x, double* y)
{
return m_trans.vertex(x, y);
}
private:
conv_stroke<gsv_text> m_polyline;
conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
};
}
#endif

View File

@@ -0,0 +1,481 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_IMAGE_ACCESSORS_INCLUDED
#define AGG_IMAGE_ACCESSORS_INCLUDED
#include "agg_basics.h"
namespace agg
{
//-----------------------------------------------------image_accessor_clip
template<class PixFmt> class image_accessor_clip
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_clip() {}
explicit image_accessor_clip(pixfmt_type& pixf,
const color_type& bk) :
m_pixf(&pixf)
{
pixfmt_type::make_pix(m_bk_buf, bk);
}
void attach(pixfmt_type& pixf)
{
m_pixf = &pixf;
}
void background_color(const color_type& bk)
{
pixfmt_type::make_pix(m_bk_buf, bk);
}
private:
AGG_INLINE const int8u* pixel() const
{
if(m_y >= 0 && m_y < (int)m_pixf->height() &&
m_x >= 0 && m_x < (int)m_pixf->width())
{
return m_pixf->pix_ptr(m_x, m_y);
}
return m_bk_buf;
}
public:
AGG_INLINE const int8u* span(int x, int y, unsigned len)
{
m_x = m_x0 = x;
m_y = y;
if(y >= 0 && y < (int)m_pixf->height() &&
x >= 0 && x+(int)len <= (int)m_pixf->width())
{
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x()
{
if(m_pix_ptr) return m_pix_ptr += pix_width;
++m_x;
return pixel();
}
AGG_INLINE const int8u* next_y()
{
++m_y;
m_x = m_x0;
if(m_pix_ptr &&
m_y >= 0 && m_y < (int)m_pixf->height())
{
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
m_pix_ptr = 0;
return pixel();
}
private:
const pixfmt_type* m_pixf;
int8u m_bk_buf[pix_width];
int m_x, m_x0, m_y;
const int8u* m_pix_ptr;
};
//--------------------------------------------------image_accessor_no_clip
template<class PixFmt> class image_accessor_no_clip
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_no_clip() {}
explicit image_accessor_no_clip(pixfmt_type& pixf) :
m_pixf(&pixf)
{}
void attach(pixfmt_type& pixf)
{
m_pixf = &pixf;
}
AGG_INLINE const int8u* span(int x, int y, unsigned)
{
m_x = x;
m_y = y;
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
AGG_INLINE const int8u* next_x()
{
return m_pix_ptr += pix_width;
}
AGG_INLINE const int8u* next_y()
{
++m_y;
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
private:
const pixfmt_type* m_pixf;
int m_x, m_y;
const int8u* m_pix_ptr;
};
//----------------------------------------------------image_accessor_clone
template<class PixFmt> class image_accessor_clone
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_clone() {}
explicit image_accessor_clone(pixfmt_type& pixf) :
m_pixf(&pixf)
{}
void attach(pixfmt_type& pixf)
{
m_pixf = &pixf;
}
private:
AGG_INLINE const int8u* pixel() const
{
int x = m_x;
int y = m_y;
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1;
if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1;
return m_pixf->pix_ptr(x, y);
}
public:
AGG_INLINE const int8u* span(int x, int y, unsigned len)
{
m_x = m_x0 = x;
m_y = y;
if(y >= 0 && y < (int)m_pixf->height() &&
x >= 0 && x+len <= (int)m_pixf->width())
{
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x()
{
if(m_pix_ptr) return m_pix_ptr += pix_width;
++m_x;
return pixel();
}
AGG_INLINE const int8u* next_y()
{
++m_y;
m_x = m_x0;
if(m_pix_ptr &&
m_y >= 0 && m_y < (int)m_pixf->height())
{
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
m_pix_ptr = 0;
return pixel();
}
private:
const pixfmt_type* m_pixf;
int m_x, m_x0, m_y;
const int8u* m_pix_ptr;
};
//-----------------------------------------------------image_accessor_wrap
template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_wrap() {}
explicit image_accessor_wrap(pixfmt_type& pixf) :
m_pixf(&pixf),
m_wrap_x(pixf.width()),
m_wrap_y(pixf.height())
{}
void attach(pixfmt_type& pixf)
{
m_pixf = &pixf;
}
AGG_INLINE const int8u* span(int x, int y, unsigned)
{
m_x = x;
m_row_ptr = m_pixf->pix_ptr(0, m_wrap_y(y));
return m_row_ptr + m_wrap_x(x) * pix_width;
}
AGG_INLINE const int8u* next_x()
{
int x = ++m_wrap_x;
return m_row_ptr + x * pix_width;
}
AGG_INLINE const int8u* next_y()
{
m_row_ptr = m_pixf->pix_ptr(0, ++m_wrap_y);
return m_row_ptr + m_wrap_x(m_x) * pix_width;
}
private:
const pixfmt_type* m_pixf;
const int8u* m_row_ptr;
int m_x;
WrapX m_wrap_x;
WrapY m_wrap_y;
};
//--------------------------------------------------------wrap_mode_repeat
class wrap_mode_repeat
{
public:
wrap_mode_repeat() {}
wrap_mode_repeat(unsigned size) :
m_size(size),
m_add(size * (0x3FFFFFFF / size)),
m_value(0)
{}
AGG_INLINE unsigned operator() (int v)
{
return m_value = (unsigned(v) + m_add) % m_size;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value >= m_size) m_value = 0;
return m_value;
}
private:
unsigned m_size;
unsigned m_add;
unsigned m_value;
};
//---------------------------------------------------wrap_mode_repeat_pow2
class wrap_mode_repeat_pow2
{
public:
wrap_mode_repeat_pow2() {}
wrap_mode_repeat_pow2(unsigned size) : m_value(0)
{
m_mask = 1;
while(m_mask < size) m_mask = (m_mask << 1) | 1;
m_mask >>= 1;
}
AGG_INLINE unsigned operator() (int v)
{
return m_value = unsigned(v) & m_mask;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value > m_mask) m_value = 0;
return m_value;
}
private:
unsigned m_mask;
unsigned m_value;
};
//----------------------------------------------wrap_mode_repeat_auto_pow2
class wrap_mode_repeat_auto_pow2
{
public:
wrap_mode_repeat_auto_pow2() {}
wrap_mode_repeat_auto_pow2(unsigned size) :
m_size(size),
m_add(size * (0x3FFFFFFF / size)),
m_mask((m_size & (m_size-1)) ? 0 : m_size-1),
m_value(0)
{}
AGG_INLINE unsigned operator() (int v)
{
if(m_mask) return m_value = unsigned(v) & m_mask;
return m_value = (unsigned(v) + m_add) % m_size;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value >= m_size) m_value = 0;
return m_value;
}
private:
unsigned m_size;
unsigned m_add;
unsigned m_mask;
unsigned m_value;
};
//-------------------------------------------------------wrap_mode_reflect
class wrap_mode_reflect
{
public:
wrap_mode_reflect() {}
wrap_mode_reflect(unsigned size) :
m_size(size),
m_size2(size * 2),
m_add(m_size2 * (0x3FFFFFFF / m_size2)),
m_value(0)
{}
AGG_INLINE unsigned operator() (int v)
{
m_value = (unsigned(v) + m_add) % m_size2;
if(m_value >= m_size) return m_size2 - m_value - 1;
return m_value;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value >= m_size2) m_value = 0;
if(m_value >= m_size) return m_size2 - m_value - 1;
return m_value;
}
private:
unsigned m_size;
unsigned m_size2;
unsigned m_add;
unsigned m_value;
};
//--------------------------------------------------wrap_mode_reflect_pow2
class wrap_mode_reflect_pow2
{
public:
wrap_mode_reflect_pow2() {}
wrap_mode_reflect_pow2(unsigned size) : m_value(0)
{
m_mask = 1;
m_size = 1;
while(m_mask < size)
{
m_mask = (m_mask << 1) | 1;
m_size <<= 1;
}
}
AGG_INLINE unsigned operator() (int v)
{
m_value = unsigned(v) & m_mask;
if(m_value >= m_size) return m_mask - m_value;
return m_value;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
m_value &= m_mask;
if(m_value >= m_size) return m_mask - m_value;
return m_value;
}
private:
unsigned m_size;
unsigned m_mask;
unsigned m_value;
};
//---------------------------------------------wrap_mode_reflect_auto_pow2
class wrap_mode_reflect_auto_pow2
{
public:
wrap_mode_reflect_auto_pow2() {}
wrap_mode_reflect_auto_pow2(unsigned size) :
m_size(size),
m_size2(size * 2),
m_add(m_size2 * (0x3FFFFFFF / m_size2)),
m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1),
m_value(0)
{}
AGG_INLINE unsigned operator() (int v)
{
m_value = m_mask ? unsigned(v) & m_mask :
(unsigned(v) + m_add) % m_size2;
if(m_value >= m_size) return m_size2 - m_value - 1;
return m_value;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value >= m_size2) m_value = 0;
if(m_value >= m_size) return m_size2 - m_value - 1;
return m_value;
}
private:
unsigned m_size;
unsigned m_size2;
unsigned m_add;
unsigned m_mask;
unsigned m_value;
};
}
#endif

View File

@@ -0,0 +1,449 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Image transformation filters,
// Filtering classes (image_filter_lut, image_filter),
// Basic filter shape classes
//----------------------------------------------------------------------------
#ifndef AGG_IMAGE_FILTERS_INCLUDED
#define AGG_IMAGE_FILTERS_INCLUDED
#include "agg_array.h"
#include "agg_math.h"
namespace agg
{
// See Implementation agg_image_filters.cpp
enum image_filter_scale_e
{
image_filter_shift = 14, //----image_filter_shift
image_filter_scale = 1 << image_filter_shift, //----image_filter_scale
image_filter_mask = image_filter_scale - 1 //----image_filter_mask
};
enum image_subpixel_scale_e
{
image_subpixel_shift = 8, //----image_subpixel_shift
image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale
image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask
};
//-----------------------------------------------------image_filter_lut
class image_filter_lut
{
public:
template<class FilterF> void calculate(const FilterF& filter,
bool normalization=true)
{
filter; // prevent erroneous C4100 in MSVC
double r = filter.radius();
realloc_lut(r);
unsigned i;
unsigned pivot = diameter() << (image_subpixel_shift - 1);
for(i = 0; i < pivot; i++)
{
double x = double(i) / double(image_subpixel_scale);
double y = filter.calc_weight(x);
m_weight_array[pivot + i] =
m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale);
}
unsigned end = (diameter() << image_subpixel_shift) - 1;
m_weight_array[0] = m_weight_array[end];
if(normalization)
{
normalize();
}
}
image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {}
template<class FilterF> image_filter_lut(const FilterF& filter,
bool normalization=true)
{
calculate(filter, normalization);
}
double radius() const { return m_radius; }
unsigned diameter() const { return m_diameter; }
int start() const { return m_start; }
const int16* weight_array() const { return &m_weight_array[0]; }
void normalize();
private:
void realloc_lut(double radius);
image_filter_lut(const image_filter_lut&);
const image_filter_lut& operator = (const image_filter_lut&);
double m_radius;
unsigned m_diameter;
int m_start;
pod_array<int16> m_weight_array;
};
//--------------------------------------------------------image_filter
template<class FilterF> class image_filter : public image_filter_lut
{
public:
image_filter()
{
calculate(m_filter_function);
}
private:
FilterF m_filter_function;
};
//-----------------------------------------------image_filter_bilinear
struct image_filter_bilinear
{
static double radius() { return 1.0; }
static double calc_weight(double x)
{
return 1.0 - x;
}
};
//-----------------------------------------------image_filter_hanning
struct image_filter_hanning
{
static double radius() { return 1.0; }
static double calc_weight(double x)
{
return 0.5 + 0.5 * std::cos(pi * x);
}
};
//-----------------------------------------------image_filter_hamming
struct image_filter_hamming
{
static double radius() { return 1.0; }
static double calc_weight(double x)
{
return 0.54 + 0.46 * std::cos(pi * x);
}
};
//-----------------------------------------------image_filter_hermite
struct image_filter_hermite
{
static double radius() { return 1.0; }
static double calc_weight(double x)
{
return (2.0 * x - 3.0) * x * x + 1.0;
}
};
//------------------------------------------------image_filter_quadric
struct image_filter_quadric
{
static double radius() { return 1.5; }
static double calc_weight(double x)
{
double t;
if(x < 0.5) return 0.75 - x * x;
if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;}
return 0.0;
}
};
//------------------------------------------------image_filter_bicubic
class image_filter_bicubic
{
static double pow3(double x)
{
return (x <= 0.0) ? 0.0 : x * x * x;
}
public:
static double radius() { return 2.0; }
static double calc_weight(double x)
{
return
(1.0/6.0) *
(pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
}
};
//-------------------------------------------------image_filter_kaiser
class image_filter_kaiser
{
double a;
double i0a;
double epsilon;
public:
image_filter_kaiser(double b = 6.33) :
a(b), epsilon(1e-12)
{
i0a = 1.0 / bessel_i0(b);
}
static double radius() { return 1.0; }
double calc_weight(double x) const
{
return bessel_i0(a * std::sqrt(1. - x * x)) * i0a;
}
private:
double bessel_i0(double x) const
{
int i;
double sum, y, t;
sum = 1.;
y = x * x / 4.;
t = y;
for(i = 2; t > epsilon; i++)
{
sum += t;
t *= (double)y / (i * i);
}
return sum;
}
};
//----------------------------------------------image_filter_catrom
struct image_filter_catrom
{
static double radius() { return 2.0; }
static double calc_weight(double x)
{
if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
return 0.;
}
};
//---------------------------------------------image_filter_mitchell
class image_filter_mitchell
{
double p0, p2, p3;
double q0, q1, q2, q3;
public:
image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) :
p0((6.0 - 2.0 * b) / 6.0),
p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0),
p3((12.0 - 9.0 * b - 6.0 * c) / 6.0),
q0((8.0 * b + 24.0 * c) / 6.0),
q1((-12.0 * b - 48.0 * c) / 6.0),
q2((6.0 * b + 30.0 * c) / 6.0),
q3((-b - 6.0 * c) / 6.0)
{}
static double radius() { return 2.0; }
double calc_weight(double x) const
{
if(x < 1.0) return p0 + x * x * (p2 + x * p3);
if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3));
return 0.0;
}
};
//----------------------------------------------image_filter_spline16
struct image_filter_spline16
{
static double radius() { return 2.0; }
static double calc_weight(double x)
{
if(x < 1.0)
{
return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
}
return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
}
};
//---------------------------------------------image_filter_spline36
struct image_filter_spline36
{
static double radius() { return 3.0; }
static double calc_weight(double x)
{
if(x < 1.0)
{
return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
}
if(x < 2.0)
{
return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1);
}
return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2);
}
};
//----------------------------------------------image_filter_gaussian
struct image_filter_gaussian
{
static double radius() { return 2.0; }
static double calc_weight(double x)
{
return std::exp(-2.0 * x * x) * std::sqrt(2.0 / pi);
}
};
//------------------------------------------------image_filter_bessel
struct image_filter_bessel
{
static double radius() { return 3.2383; }
static double calc_weight(double x)
{
return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x);
}
};
//-------------------------------------------------image_filter_sinc
class image_filter_sinc
{
public:
image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
double radius() const { return m_radius; }
double calc_weight(double x) const
{
if(x == 0.0) return 1.0;
x *= pi;
return std::sin(x) / x;
}
private:
double m_radius;
};
//-----------------------------------------------image_filter_lanczos
class image_filter_lanczos
{
public:
image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
double radius() const { return m_radius; }
double calc_weight(double x) const
{
if(x == 0.0) return 1.0;
if(x > m_radius) return 0.0;
x *= pi;
double xr = x / m_radius;
return (std::sin(x) / x) * (std::sin(xr) / xr);
}
private:
double m_radius;
};
//----------------------------------------------image_filter_blackman
class image_filter_blackman
{
public:
image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {}
double radius() const { return m_radius; }
double calc_weight(double x) const
{
if(x == 0.0) return 1.0;
if(x > m_radius) return 0.0;
x *= pi;
double xr = x / m_radius;
return (std::sin(x) / x) * (0.42 + 0.5*std::cos(xr) + 0.08*std::cos(2*xr));
}
private:
double m_radius;
};
//------------------------------------------------image_filter_sinc36
class image_filter_sinc36 : public image_filter_sinc
{ public: image_filter_sinc36() : image_filter_sinc(3.0){} };
//------------------------------------------------image_filter_sinc64
class image_filter_sinc64 : public image_filter_sinc
{ public: image_filter_sinc64() : image_filter_sinc(4.0){} };
//-----------------------------------------------image_filter_sinc100
class image_filter_sinc100 : public image_filter_sinc
{ public: image_filter_sinc100() : image_filter_sinc(5.0){} };
//-----------------------------------------------image_filter_sinc144
class image_filter_sinc144 : public image_filter_sinc
{ public: image_filter_sinc144() : image_filter_sinc(6.0){} };
//-----------------------------------------------image_filter_sinc196
class image_filter_sinc196 : public image_filter_sinc
{ public: image_filter_sinc196() : image_filter_sinc(7.0){} };
//-----------------------------------------------image_filter_sinc256
class image_filter_sinc256 : public image_filter_sinc
{ public: image_filter_sinc256() : image_filter_sinc(8.0){} };
//---------------------------------------------image_filter_lanczos36
class image_filter_lanczos36 : public image_filter_lanczos
{ public: image_filter_lanczos36() : image_filter_lanczos(3.0){} };
//---------------------------------------------image_filter_lanczos64
class image_filter_lanczos64 : public image_filter_lanczos
{ public: image_filter_lanczos64() : image_filter_lanczos(4.0){} };
//--------------------------------------------image_filter_lanczos100
class image_filter_lanczos100 : public image_filter_lanczos
{ public: image_filter_lanczos100() : image_filter_lanczos(5.0){} };
//--------------------------------------------image_filter_lanczos144
class image_filter_lanczos144 : public image_filter_lanczos
{ public: image_filter_lanczos144() : image_filter_lanczos(6.0){} };
//--------------------------------------------image_filter_lanczos196
class image_filter_lanczos196 : public image_filter_lanczos
{ public: image_filter_lanczos196() : image_filter_lanczos(7.0){} };
//--------------------------------------------image_filter_lanczos256
class image_filter_lanczos256 : public image_filter_lanczos
{ public: image_filter_lanczos256() : image_filter_lanczos(8.0){} };
//--------------------------------------------image_filter_blackman36
class image_filter_blackman36 : public image_filter_blackman
{ public: image_filter_blackman36() : image_filter_blackman(3.0){} };
//--------------------------------------------image_filter_blackman64
class image_filter_blackman64 : public image_filter_blackman
{ public: image_filter_blackman64() : image_filter_blackman(4.0){} };
//-------------------------------------------image_filter_blackman100
class image_filter_blackman100 : public image_filter_blackman
{ public: image_filter_blackman100() : image_filter_blackman(5.0){} };
//-------------------------------------------image_filter_blackman144
class image_filter_blackman144 : public image_filter_blackman
{ public: image_filter_blackman144() : image_filter_blackman(6.0){} };
//-------------------------------------------image_filter_blackman196
class image_filter_blackman196 : public image_filter_blackman
{ public: image_filter_blackman196() : image_filter_blackman(7.0){} };
//-------------------------------------------image_filter_blackman256
class image_filter_blackman256 : public image_filter_blackman
{ public: image_filter_blackman256() : image_filter_blackman(8.0){} };
}
#endif

View File

@@ -0,0 +1,189 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_LINE_AA_BASICS_INCLUDED
#define AGG_LINE_AA_BASICS_INCLUDED
#include <cstdlib>
#include "agg_basics.h"
namespace agg
{
// See Implementation agg_line_aa_basics.cpp
//-------------------------------------------------------------------------
enum line_subpixel_scale_e
{
line_subpixel_shift = 8, //----line_subpixel_shift
line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale
line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask
line_max_coord = (1 << 28) - 1, //----line_max_coord
line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length
};
//-------------------------------------------------------------------------
enum line_mr_subpixel_scale_e
{
line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift
line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale
line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask
};
//------------------------------------------------------------------line_mr
AGG_INLINE int line_mr(int x)
{
return x >> (line_subpixel_shift - line_mr_subpixel_shift);
}
//-------------------------------------------------------------------line_hr
AGG_INLINE int line_hr(int x)
{
return x << (line_subpixel_shift - line_mr_subpixel_shift);
}
//---------------------------------------------------------------line_dbl_hr
AGG_INLINE int line_dbl_hr(int x)
{
return x << line_subpixel_shift;
}
//---------------------------------------------------------------line_coord
struct line_coord
{
AGG_INLINE static int conv(double x)
{
return iround(x * line_subpixel_scale);
}
};
//-----------------------------------------------------------line_coord_sat
struct line_coord_sat
{
AGG_INLINE static int conv(double x)
{
return saturation<line_max_coord>::iround(x * line_subpixel_scale);
}
};
//==========================================================line_parameters
struct line_parameters
{
//---------------------------------------------------------------------
line_parameters() {}
line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_),
dx(std::abs(x2_ - x1_)),
dy(std::abs(y2_ - y1_)),
sx((x2_ > x1_) ? 1 : -1),
sy((y2_ > y1_) ? 1 : -1),
vertical(dy >= dx),
inc(vertical ? sy : sx),
len(len_),
octant((sy & 4) | (sx & 2) | int(vertical))
{
}
//---------------------------------------------------------------------
unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; }
unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; }
//---------------------------------------------------------------------
bool same_orthogonal_quadrant(const line_parameters& lp) const
{
return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant];
}
//---------------------------------------------------------------------
bool same_diagonal_quadrant(const line_parameters& lp) const
{
return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant];
}
//---------------------------------------------------------------------
void divide(line_parameters& lp1, line_parameters& lp2) const
{
int xmid = (x1 + x2) >> 1;
int ymid = (y1 + y2) >> 1;
int len2 = len >> 1;
lp1 = *this;
lp2 = *this;
lp1.x2 = xmid;
lp1.y2 = ymid;
lp1.len = len2;
lp1.dx = std::abs(lp1.x2 - lp1.x1);
lp1.dy = std::abs(lp1.y2 - lp1.y1);
lp2.x1 = xmid;
lp2.y1 = ymid;
lp2.len = len2;
lp2.dx = std::abs(lp2.x2 - lp2.x1);
lp2.dy = std::abs(lp2.y2 - lp2.y1);
}
//---------------------------------------------------------------------
int x1, y1, x2, y2, dx, dy, sx, sy;
bool vertical;
int inc;
int len;
int octant;
//---------------------------------------------------------------------
static const int8u s_orthogonal_quadrant[8];
static const int8u s_diagonal_quadrant[8];
};
// See Implementation agg_line_aa_basics.cpp
//----------------------------------------------------------------bisectrix
void bisectrix(const line_parameters& l1,
const line_parameters& l2,
int* x, int* y);
//-------------------------------------------fix_degenerate_bisectrix_start
void inline fix_degenerate_bisectrix_start(const line_parameters& lp,
int* x, int* y)
{
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
if(d < line_subpixel_scale/2)
{
*x = lp.x1 + (lp.y2 - lp.y1);
*y = lp.y1 - (lp.x2 - lp.x1);
}
}
//---------------------------------------------fix_degenerate_bisectrix_end
void inline fix_degenerate_bisectrix_end(const line_parameters& lp,
int* x, int* y)
{
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
if(d < line_subpixel_scale/2)
{
*x = lp.x2 + (lp.y2 - lp.y1);
*y = lp.y2 - (lp.x2 - lp.x1);
}
}
}
#endif

437
dep/agg/include/agg_math.h Normal file
View File

@@ -0,0 +1,437 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
// Contact: castor.vulgaris@gmail.com
//----------------------------------------------------------------------------
#ifndef AGG_MATH_INCLUDED
#define AGG_MATH_INCLUDED
#include <cmath>
#include "agg_basics.h"
namespace agg
{
//------------------------------------------------------vertex_dist_epsilon
// Coinciding points maximal distance (Epsilon)
const double vertex_dist_epsilon = 1e-14;
//-----------------------------------------------------intersection_epsilon
// See calc_intersection
const double intersection_epsilon = 1.0e-30;
//------------------------------------------------------------cross_product
AGG_INLINE double cross_product(double x1, double y1,
double x2, double y2,
double x, double y)
{
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
}
//--------------------------------------------------------point_in_triangle
AGG_INLINE bool point_in_triangle(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x, double y)
{
bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
}
//-----------------------------------------------------------calc_distance
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
{
double dx = x2-x1;
double dy = y2-y1;
return std::sqrt(dx * dx + dy * dy);
}
//--------------------------------------------------------calc_sq_distance
AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
{
double dx = x2-x1;
double dy = y2-y1;
return dx * dx + dy * dy;
}
//------------------------------------------------calc_line_point_distance
AGG_INLINE double calc_line_point_distance(double x1, double y1,
double x2, double y2,
double x, double y)
{
double dx = x2-x1;
double dy = y2-y1;
double d = std::sqrt(dx * dx + dy * dy);
if(d < vertex_dist_epsilon)
{
return calc_distance(x1, y1, x, y);
}
return ((x - x2) * dy - (y - y2) * dx) / d;
}
//-------------------------------------------------------calc_line_point_u
AGG_INLINE double calc_segment_point_u(double x1, double y1,
double x2, double y2,
double x, double y)
{
double dx = x2 - x1;
double dy = y2 - y1;
if(dx == 0 && dy == 0)
{
return 0;
}
double pdx = x - x1;
double pdy = y - y1;
return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
}
//---------------------------------------------calc_line_point_sq_distance
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
double x2, double y2,
double x, double y,
double u)
{
if(u <= 0)
{
return calc_sq_distance(x, y, x1, y1);
}
else
if(u >= 1)
{
return calc_sq_distance(x, y, x2, y2);
}
return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
}
//---------------------------------------------calc_line_point_sq_distance
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
double x2, double y2,
double x, double y)
{
return
calc_segment_point_sq_distance(
x1, y1, x2, y2, x, y,
calc_segment_point_u(x1, y1, x2, y2, x, y));
}
//-------------------------------------------------------calc_intersection
AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
double cx, double cy, double dx, double dy,
double* x, double* y)
{
double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
if(std::fabs(den) < intersection_epsilon) return false;
double r = num / den;
*x = ax + r * (bx-ax);
*y = ay + r * (by-ay);
return true;
}
//-----------------------------------------------------intersection_exists
AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
double x3, double y3, double x4, double y4)
{
// It's less expensive but you can't control the
// boundary conditions: Less or LessEqual
double dx1 = x2 - x1;
double dy1 = y2 - y1;
double dx2 = x4 - x3;
double dy2 = y4 - y3;
return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) !=
((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) !=
((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
// It's is more expensive but more flexible
// in terms of boundary conditions.
//--------------------
//double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
//if(fabs(den) < intersection_epsilon) return false;
//double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
//double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
//double ua = nom1 / den;
//double ub = nom2 / den;
//return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
}
//--------------------------------------------------------calc_orthogonal
AGG_INLINE void calc_orthogonal(double thickness,
double x1, double y1,
double x2, double y2,
double* x, double* y)
{
double dx = x2 - x1;
double dy = y2 - y1;
double d = std::sqrt(dx*dx + dy*dy);
*x = thickness * dy / d;
*y = -thickness * dx / d;
}
//--------------------------------------------------------dilate_triangle
AGG_INLINE void dilate_triangle(double x1, double y1,
double x2, double y2,
double x3, double y3,
double *x, double* y,
double d)
{
double dx1=0.0;
double dy1=0.0;
double dx2=0.0;
double dy2=0.0;
double dx3=0.0;
double dy3=0.0;
double loc = cross_product(x1, y1, x2, y2, x3, y3);
if(std::fabs(loc) > intersection_epsilon)
{
if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0)
{
d = -d;
}
calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
}
*x++ = x1 + dx1; *y++ = y1 + dy1;
*x++ = x2 + dx1; *y++ = y2 + dy1;
*x++ = x2 + dx2; *y++ = y2 + dy2;
*x++ = x3 + dx2; *y++ = y3 + dy2;
*x++ = x3 + dx3; *y++ = y3 + dy3;
*x++ = x1 + dx3; *y++ = y1 + dy3;
}
//------------------------------------------------------calc_triangle_area
AGG_INLINE double calc_triangle_area(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
}
//-------------------------------------------------------calc_polygon_area
template<class Storage> double calc_polygon_area(const Storage& st)
{
unsigned i;
double sum = 0.0;
double x = st[0].x;
double y = st[0].y;
double xs = x;
double ys = y;
for(i = 1; i < st.size(); i++)
{
const typename Storage::value_type& v = st[i];
sum += x * v.y - y * v.x;
x = v.x;
y = v.y;
}
return (sum + x * ys - y * xs) * 0.5;
}
//------------------------------------------------------------------------
// Tables for fast sqrt
extern int16u g_sqrt_table[1024];
extern int8 g_elder_bit_table[256];
//---------------------------------------------------------------fast_sqrt
//Fast integer Sqrt - really fast: no cycles, divisions or multiplications
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4035) //Disable warning "no return value"
#endif
AGG_INLINE unsigned fast_sqrt(unsigned val)
{
#if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
//For Ix86 family processors this assembler code is used.
//The key command here is bsr - determination the number of the most
//significant bit of the value. For other processors
//(and maybe compilers) the pure C "#else" section is used.
__asm
{
mov ebx, val
mov edx, 11
bsr ecx, ebx
sub ecx, 9
jle less_than_9_bits
shr ecx, 1
adc ecx, 0
sub edx, ecx
shl ecx, 1
shr ebx, cl
less_than_9_bits:
xor eax, eax
mov ax, g_sqrt_table[ebx*2]
mov ecx, edx
shr eax, cl
}
#else
//This code is actually pure C and portable to most
//arcitectures including 64bit ones.
unsigned t = val;
int bit=0;
unsigned shift = 11;
//The following piece of code is just an emulation of the
//Ix86 assembler command "bsr" (see above). However on old
//Intels (like Intel MMX 233MHz) this code is about twice
//faster (sic!) then just one "bsr". On PIII and PIV the
//bsr is optimized quite well.
bit = t >> 24;
if(bit)
{
bit = g_elder_bit_table[bit] + 24;
}
else
{
bit = (t >> 16) & 0xFF;
if(bit)
{
bit = g_elder_bit_table[bit] + 16;
}
else
{
bit = (t >> 8) & 0xFF;
if(bit)
{
bit = g_elder_bit_table[bit] + 8;
}
else
{
bit = g_elder_bit_table[t];
}
}
}
//This code calculates the sqrt.
bit -= 9;
if(bit > 0)
{
bit = (bit >> 1) + (bit & 1);
shift -= bit;
val >>= (bit << 1);
}
return g_sqrt_table[val] >> shift;
#endif
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
//--------------------------------------------------------------------besj
// Function BESJ calculates Bessel function of first kind of order n
// Arguments:
// n - an integer (>=0), the order
// x - value at which the Bessel function is required
//--------------------
// C++ Mathematical Library
// Convereted from equivalent FORTRAN library
// Converetd by Gareth Walker for use by course 392 computational project
// All functions tested and yield the same results as the corresponding
// FORTRAN versions.
//
// If you have any problems using these functions please report them to
// M.Muldoon@UMIST.ac.uk
//
// Documentation available on the web
// http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
// Version 1.0 8/98
// 29 October, 1999
//--------------------
// Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
//------------------------------------------------------------------------
inline double besj(double x, int n)
{
if(n < 0)
{
return 0;
}
double d = 1E-6;
double b = 0;
if(std::fabs(x) <= d)
{
if(n != 0) return 0;
return 1;
}
double b1 = 0; // b1 is the value from the previous iteration
// Set up a starting order for recurrence
int m1 = (int)std::fabs(x) + 6;
if(std::fabs(x) > 5)
{
m1 = (int)(std::fabs(1.4 * x + 60 / x));
}
int m2 = (int)(n + 2 + std::fabs(x) / 4);
if (m1 > m2)
{
m2 = m1;
}
// Apply recurrence down from curent max order
for(;;)
{
double c3 = 0;
double c2 = 1E-30;
double c4 = 0;
int m8 = 1;
if (m2 / 2 * 2 == m2)
{
m8 = -1;
}
int imax = m2 - 2;
for (int i = 1; i <= imax; i++)
{
double c6 = 2 * (m2 - i) * c2 / x - c3;
c3 = c2;
c2 = c6;
if(m2 - i - 1 == n)
{
b = c6;
}
m8 = -1 * m8;
if (m8 > 0)
{
c4 = c4 + 2 * c6;
}
}
double c6 = 2 * c2 / x - c3;
if(n == 0)
{
b = c6;
}
c4 += c6;
b /= c4;
if(std::fabs(b - b1) < d)
{
return b;
}
b1 = b;
m2 += 3;
}
}
}
#endif

View File

@@ -0,0 +1,526 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Stroke math
//
//----------------------------------------------------------------------------
#ifndef AGG_STROKE_MATH_INCLUDED
#define AGG_STROKE_MATH_INCLUDED
#include "agg_math.h"
#include "agg_vertex_sequence.h"
namespace agg
{
//-------------------------------------------------------------line_cap_e
enum line_cap_e
{
butt_cap,
square_cap,
round_cap
};
//------------------------------------------------------------line_join_e
enum line_join_e
{
miter_join = 0,
miter_join_revert = 1,
round_join = 2,
bevel_join = 3,
miter_join_round = 4
};
//-----------------------------------------------------------inner_join_e
enum inner_join_e
{
inner_bevel,
inner_miter,
inner_jag,
inner_round
};
//------------------------------------------------------------math_stroke
template<class VertexConsumer> class math_stroke
{
public:
typedef typename VertexConsumer::value_type coord_type;
math_stroke();
void line_cap(line_cap_e lc) { m_line_cap = lc; }
void line_join(line_join_e lj) { m_line_join = lj; }
void inner_join(inner_join_e ij) { m_inner_join = ij; }
line_cap_e line_cap() const { return m_line_cap; }
line_join_e line_join() const { return m_line_join; }
inner_join_e inner_join() const { return m_inner_join; }
void width(double w);
void miter_limit(double ml) { m_miter_limit = ml; }
void miter_limit_theta(double t);
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
void approximation_scale(double as) { m_approx_scale = as; }
double width() const { return m_width * 2.0; }
double miter_limit() const { return m_miter_limit; }
double inner_miter_limit() const { return m_inner_miter_limit; }
double approximation_scale() const { return m_approx_scale; }
void calc_cap(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
double len);
void calc_join(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double len1,
double len2);
private:
AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y)
{
vc.add(coord_type(x, y));
}
void calc_arc(VertexConsumer& vc,
double x, double y,
double dx1, double dy1,
double dx2, double dy2);
void calc_miter(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double dx1, double dy1,
double dx2, double dy2,
line_join_e lj,
double mlimit,
double dbevel);
double m_width;
double m_width_abs;
double m_width_eps;
int m_width_sign;
double m_miter_limit;
double m_inner_miter_limit;
double m_approx_scale;
line_cap_e m_line_cap;
line_join_e m_line_join;
inner_join_e m_inner_join;
};
//-----------------------------------------------------------------------
template<class VC> math_stroke<VC>::math_stroke() :
m_width(0.5),
m_width_abs(0.5),
m_width_eps(0.5/1024.0),
m_width_sign(1),
m_miter_limit(4.0),
m_inner_miter_limit(1.01),
m_approx_scale(1.0),
m_line_cap(butt_cap),
m_line_join(miter_join),
m_inner_join(inner_miter)
{
}
//-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::width(double w)
{
m_width = w * 0.5;
if(m_width < 0)
{
m_width_abs = -m_width;
m_width_sign = -1;
}
else
{
m_width_abs = m_width;
m_width_sign = 1;
}
m_width_eps = m_width / 1024.0;
}
//-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::miter_limit_theta(double t)
{
m_miter_limit = 1.0 / std::sin(t * 0.5) ;
}
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::calc_arc(VC& vc,
double x, double y,
double dx1, double dy1,
double dx2, double dy2)
{
double a1 = std::atan2(dy1 * m_width_sign, dx1 * m_width_sign);
double a2 = std::atan2(dy2 * m_width_sign, dx2 * m_width_sign);
double da = a1 - a2;
int i, n;
da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
add_vertex(vc, x + dx1, y + dy1);
if(m_width_sign > 0)
{
if(a1 > a2) a2 += 2 * pi;
n = int((a2 - a1) / da);
da = (a2 - a1) / (n + 1);
a1 += da;
for(i = 0; i < n; i++)
{
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
a1 += da;
}
}
else
{
if(a1 < a2) a2 -= 2 * pi;
n = int((a1 - a2) / da);
da = (a1 - a2) / (n + 1);
a1 -= da;
for(i = 0; i < n; i++)
{
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
a1 -= da;
}
}
add_vertex(vc, x + dx2, y + dy2);
}
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::calc_miter(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double dx1, double dy1,
double dx2, double dy2,
line_join_e lj,
double mlimit,
double dbevel)
{
double xi = v1.x;
double yi = v1.y;
double di = 1;
double lim = m_width_abs * mlimit;
bool miter_limit_exceeded = true; // Assume the worst
bool intersection_failed = true; // Assume the worst
if(calc_intersection(v0.x + dx1, v0.y - dy1,
v1.x + dx1, v1.y - dy1,
v1.x + dx2, v1.y - dy2,
v2.x + dx2, v2.y - dy2,
&xi, &yi))
{
// Calculation of the intersection succeeded
//---------------------
di = calc_distance(v1.x, v1.y, xi, yi);
if(di <= lim)
{
// Inside the miter limit
//---------------------
add_vertex(vc, xi, yi);
miter_limit_exceeded = false;
}
intersection_failed = false;
}
else
{
// Calculation of the intersection failed, most probably
// the three points lie one straight line.
// First check if v0 and v2 lie on the opposite sides of vector:
// (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
// to the line determined by vertices v0 and v1.
// This condition determines whether the next line segments continues
// the previous one or goes back.
//----------------
double x2 = v1.x + dx1;
double y2 = v1.y - dy1;
if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
(cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
{
// This case means that the next segment continues
// the previous one (straight line)
//-----------------
add_vertex(vc, v1.x + dx1, v1.y - dy1);
miter_limit_exceeded = false;
}
}
if(miter_limit_exceeded)
{
// Miter limit exceeded
//------------------------
switch(lj)
{
case miter_join_revert:
// For the compatibility with SVG, PDF, etc,
// we use a simple bevel join instead of
// "smart" bevel
//-------------------
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2);
break;
case miter_join_round:
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
break;
default:
// If no miter-revert, calculate new dx1, dy1, dx2, dy2
//----------------
if(intersection_failed)
{
mlimit *= m_width_sign;
add_vertex(vc, v1.x + dx1 + dy1 * mlimit,
v1.y - dy1 + dx1 * mlimit);
add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
v1.y - dy2 - dx2 * mlimit);
}
else
{
double x1 = v1.x + dx1;
double y1 = v1.y - dy1;
double x2 = v1.x + dx2;
double y2 = v1.y - dy2;
di = (lim - dbevel) / (di - dbevel);
add_vertex(vc, x1 + (xi - x1) * di,
y1 + (yi - y1) * di);
add_vertex(vc, x2 + (xi - x2) * di,
y2 + (yi - y2) * di);
}
break;
}
}
}
//--------------------------------------------------------stroke_calc_cap
template<class VC>
void math_stroke<VC>::calc_cap(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
double len)
{
vc.remove_all();
double dx1 = (v1.y - v0.y) / len;
double dy1 = (v1.x - v0.x) / len;
double dx2 = 0;
double dy2 = 0;
dx1 *= m_width;
dy1 *= m_width;
if(m_line_cap != round_cap)
{
if(m_line_cap == square_cap)
{
dx2 = dy1 * m_width_sign;
dy2 = dx1 * m_width_sign;
}
add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
}
else
{
double da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
double a1;
int i;
int n = int(pi / da);
da = pi / (n + 1);
add_vertex(vc, v0.x - dx1, v0.y + dy1);
if(m_width_sign > 0)
{
a1 = std::atan2(dy1, -dx1);
a1 += da;
for(i = 0; i < n; i++)
{
add_vertex(vc, v0.x + std::cos(a1) * m_width,
v0.y + std::sin(a1) * m_width);
a1 += da;
}
}
else
{
a1 = std::atan2(-dy1, dx1);
a1 -= da;
for(i = 0; i < n; i++)
{
add_vertex(vc, v0.x + std::cos(a1) * m_width,
v0.y + std::sin(a1) * m_width);
a1 -= da;
}
}
add_vertex(vc, v0.x + dx1, v0.y - dy1);
}
}
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::calc_join(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double len1,
double len2)
{
double dx1 = m_width * (v1.y - v0.y) / len1;
double dy1 = m_width * (v1.x - v0.x) / len1;
double dx2 = m_width * (v2.y - v1.y) / len2;
double dy2 = m_width * (v2.x - v1.x) / len2;
vc.remove_all();
double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
if(cp != 0 && (cp > 0) == (m_width > 0))
{
// Inner join
//---------------
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
if(limit < m_inner_miter_limit)
{
limit = m_inner_miter_limit;
}
switch(m_inner_join)
{
default: // inner_bevel
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2);
break;
case inner_miter:
calc_miter(vc,
v0, v1, v2, dx1, dy1, dx2, dy2,
miter_join_revert,
limit, 0);
break;
case inner_jag:
case inner_round:
cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
if(cp < len1 * len1 && cp < len2 * len2)
{
calc_miter(vc,
v0, v1, v2, dx1, dy1, dx2, dy2,
miter_join_revert,
limit, 0);
}
else
{
if(m_inner_join == inner_jag)
{
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x, v1.y );
add_vertex(vc, v1.x + dx2, v1.y - dy2);
}
else
{
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x, v1.y );
calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
add_vertex(vc, v1.x, v1.y );
add_vertex(vc, v1.x + dx2, v1.y - dy2);
}
}
break;
}
}
else
{
// Outer join
//---------------
// Calculate the distance between v1 and
// the central point of the bevel line segment
//---------------
double dx = (dx1 + dx2) / 2;
double dy = (dy1 + dy2) / 2;
double dbevel = std::sqrt(dx * dx + dy * dy);
if(m_line_join == round_join || m_line_join == bevel_join)
{
// This is an optimization that reduces the number of points
// in cases of almost collinear segments. If there's no
// visible difference between bevel and miter joins we'd rather
// use miter join because it adds only one point instead of two.
//
// Here we calculate the middle point between the bevel points
// and then, the distance between v1 and this middle point.
// At outer joins this distance always less than stroke width,
// because it's actually the height of an isosceles triangle of
// v1 and its two bevel points. If the difference between this
// width and this value is small (no visible bevel) we can
// add just one point.
//
// The constant in the expression makes the result approximately
// the same as in round joins and caps. You can safely comment
// out this entire "if".
//-------------------
if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
{
if(calc_intersection(v0.x + dx1, v0.y - dy1,
v1.x + dx1, v1.y - dy1,
v1.x + dx2, v1.y - dy2,
v2.x + dx2, v2.y - dy2,
&dx, &dy))
{
add_vertex(vc, dx, dy);
}
else
{
add_vertex(vc, v1.x + dx1, v1.y - dy1);
}
return;
}
}
switch(m_line_join)
{
case miter_join:
case miter_join_revert:
case miter_join_round:
calc_miter(vc,
v0, v1, v2, dx1, dy1, dx2, dy2,
m_line_join,
m_miter_limit,
dbevel);
break;
case round_join:
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
break;
default: // Bevel join
add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2);
break;
}
}
}
}
#endif

View File

@@ -0,0 +1,65 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PATH_LENGTH_INCLUDED
#define AGG_PATH_LENGTH_INCLUDED
#include "agg_math.h"
namespace agg
{
template<class VertexSource>
double path_length(VertexSource& vs, unsigned path_id = 0)
{
double len = 0.0;
double start_x = 0.0;
double start_y = 0.0;
double x1 = 0.0;
double y1 = 0.0;
double x2 = 0.0;
double y2 = 0.0;
bool first = true;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x2, &y2)))
{
if(is_vertex(cmd))
{
if(first || is_move_to(cmd))
{
start_x = x2;
start_y = y2;
}
else
{
len += calc_distance(x1, y1, x2, y2);
}
x1 = x2;
y1 = y2;
first = false;
}
else
{
if(is_close(cmd) && !first)
{
len += calc_distance(x1, y1, start_x, start_y);
}
}
}
return len;
}
}
#endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,295 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED
#define AGG_PATH_STORAGE_INTEGER_INCLUDED
#include <cstring>
#include "agg_array.h"
namespace agg
{
//---------------------------------------------------------vertex_integer
template<class T, unsigned CoordShift=6> struct vertex_integer
{
enum path_cmd
{
cmd_move_to = 0,
cmd_line_to = 1,
cmd_curve3 = 2,
cmd_curve4 = 3
};
enum coord_scale_e
{
coord_shift = CoordShift,
coord_scale = 1 << coord_shift
};
T x,y;
vertex_integer() {}
vertex_integer(T x_, T y_, unsigned flag) :
x(((x_ << 1) & ~1) | (flag & 1)),
y(((y_ << 1) & ~1) | (flag >> 1)) {}
unsigned vertex(double* x_, double* y_,
double dx=0, double dy=0,
double scale=1.0) const
{
*x_ = dx + (double(x >> 1) / coord_scale) * scale;
*y_ = dy + (double(y >> 1) / coord_scale) * scale;
switch(((y & 1) << 1) | (x & 1))
{
case cmd_move_to: return path_cmd_move_to;
case cmd_line_to: return path_cmd_line_to;
case cmd_curve3: return path_cmd_curve3;
case cmd_curve4: return path_cmd_curve4;
}
return path_cmd_stop;
}
};
//---------------------------------------------------path_storage_integer
template<class T, unsigned CoordShift=6> class path_storage_integer
{
public:
typedef T value_type;
typedef vertex_integer<T, CoordShift> vertex_integer_type;
//--------------------------------------------------------------------
path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {}
//--------------------------------------------------------------------
void remove_all() { m_storage.remove_all(); }
//--------------------------------------------------------------------
void move_to(T x, T y)
{
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
}
//--------------------------------------------------------------------
void line_to(T x, T y)
{
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to));
}
//--------------------------------------------------------------------
void curve3(T x_ctrl, T y_ctrl,
T x_to, T y_to)
{
m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3));
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3));
}
//--------------------------------------------------------------------
void curve4(T x_ctrl1, T y_ctrl1,
T x_ctrl2, T y_ctrl2,
T x_to, T y_to)
{
m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4));
m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4));
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4));
}
//--------------------------------------------------------------------
void close_polygon() {}
//--------------------------------------------------------------------
unsigned size() const { return m_storage.size(); }
unsigned vertex(unsigned idx, double* x, double* y) const
{
return m_storage[idx].vertex(x, y);
}
//--------------------------------------------------------------------
unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); }
void serialize(int8u* ptr) const
{
unsigned i;
for(i = 0; i < m_storage.size(); i++)
{
std::memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
ptr += sizeof(vertex_integer_type);
}
}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_vertex_idx = 0;
m_closed = true;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if(m_storage.size() < 2 || m_vertex_idx > m_storage.size())
{
*x = 0;
*y = 0;
return path_cmd_stop;
}
if(m_vertex_idx == m_storage.size())
{
*x = 0;
*y = 0;
++m_vertex_idx;
return path_cmd_end_poly | path_flags_close;
}
unsigned cmd = m_storage[m_vertex_idx].vertex(x, y);
if(is_move_to(cmd) && !m_closed)
{
*x = 0;
*y = 0;
m_closed = true;
return path_cmd_end_poly | path_flags_close;
}
m_closed = false;
++m_vertex_idx;
return cmd;
}
//--------------------------------------------------------------------
rect_d bounding_rect() const
{
rect_d bounds(1e100, 1e100, -1e100, -1e100);
if(m_storage.size() == 0)
{
bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
}
else
{
unsigned i;
for(i = 0; i < m_storage.size(); i++)
{
double x, y;
m_storage[i].vertex(&x, &y);
if(x < bounds.x1) bounds.x1 = x;
if(y < bounds.y1) bounds.y1 = y;
if(x > bounds.x2) bounds.x2 = x;
if(y > bounds.y2) bounds.y2 = y;
}
}
return bounds;
}
private:
pod_bvector<vertex_integer_type, 6> m_storage;
unsigned m_vertex_idx;
bool m_closed;
};
//-----------------------------------------serialized_integer_path_adaptor
template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
{
public:
typedef vertex_integer<T, CoordShift> vertex_integer_type;
//--------------------------------------------------------------------
serialized_integer_path_adaptor() :
m_data(0),
m_end(0),
m_ptr(0),
m_dx(0.0),
m_dy(0.0),
m_scale(1.0),
m_vertices(0)
{}
//--------------------------------------------------------------------
serialized_integer_path_adaptor(const int8u* data, unsigned size,
double dx, double dy) :
m_data(data),
m_end(data + size),
m_ptr(data),
m_dx(dx),
m_dy(dy),
m_vertices(0)
{}
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size,
double dx, double dy, double scale=1.0)
{
m_data = data;
m_end = data + size;
m_ptr = data;
m_dx = dx;
m_dy = dy;
m_scale = scale;
m_vertices = 0;
}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_ptr = m_data;
m_vertices = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if(m_data == 0 || m_ptr > m_end)
{
*x = 0;
*y = 0;
return path_cmd_stop;
}
if(m_ptr == m_end)
{
*x = 0;
*y = 0;
m_ptr += sizeof(vertex_integer_type);
return path_cmd_end_poly | path_flags_close;
}
vertex_integer_type v;
std::memcpy(&v, m_ptr, sizeof(vertex_integer_type));
unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
if(is_move_to(cmd) && m_vertices > 2)
{
*x = 0;
*y = 0;
m_vertices = 0;
return path_cmd_end_poly | path_flags_close;
}
++m_vertices;
m_ptr += sizeof(vertex_integer_type);
return cmd;
}
private:
const int8u* m_data;
const int8u* m_end;
const int8u* m_ptr;
double m_dx;
double m_dy;
double m_scale;
unsigned m_vertices;
};
}
#endif

View File

@@ -0,0 +1,123 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PATTERN_FILTERS_RGBA8_INCLUDED
#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED
#include "agg_basics.h"
#include "agg_line_aa_basics.h"
#include "agg_color_rgba.h"
namespace agg
{
//=======================================================pattern_filter_nn
template<class ColorT> struct pattern_filter_nn
{
typedef ColorT color_type;
static unsigned dilation() { return 0; }
static void AGG_INLINE pixel_low_res(color_type const* const* buf,
color_type* p, int x, int y)
{
*p = buf[y][x];
}
static void AGG_INLINE pixel_high_res(color_type const* const* buf,
color_type* p, int x, int y)
{
*p = buf[y >> line_subpixel_shift]
[x >> line_subpixel_shift];
}
};
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16;
//===========================================pattern_filter_bilinear_rgba
template<class ColorT> struct pattern_filter_bilinear_rgba
{
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
static unsigned dilation() { return 1; }
static AGG_INLINE void pixel_low_res(color_type const* const* buf,
color_type* p, int x, int y)
{
*p = buf[y][x];
}
static AGG_INLINE void pixel_high_res(color_type const* const* buf,
color_type* p, int x, int y)
{
calc_type r, g, b, a;
r = g = b = a = 0;
calc_type weight;
int x_lr = x >> line_subpixel_shift;
int y_lr = y >> line_subpixel_shift;
x &= line_subpixel_mask;
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
weight = (line_subpixel_scale - x) *
(line_subpixel_scale - y);
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
++ptr;
weight = x * (line_subpixel_scale - y);
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
ptr = buf[y_lr + 1] + x_lr;
weight = (line_subpixel_scale - x) * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
++ptr;
weight = x * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
p->r = (value_type)color_type::downshift(r, line_subpixel_shift * 2);
p->g = (value_type)color_type::downshift(g, line_subpixel_shift * 2);
p->b = (value_type)color_type::downshift(b, line_subpixel_shift * 2);
p->a = (value_type)color_type::downshift(a, line_subpixel_shift * 2);
}
};
typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8;
typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16;
typedef pattern_filter_bilinear_rgba<rgba32> pattern_filter_bilinear_rgba32;
}
#endif

View File

@@ -0,0 +1,240 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
#include <cstring>
#include "agg_array.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//==================================================pixfmt_amask_adaptor
template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef AlphaMask amask_type;
typedef typename amask_type::cover_type cover_type;
private:
enum span_extra_tail_e { span_extra_tail = 256 };
void realloc_span(unsigned len)
{
if(len > m_span.size())
{
m_span.resize(len + span_extra_tail);
}
}
void init_span(unsigned len)
{
realloc_span(len);
std::memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
}
void init_span(unsigned len, const cover_type* covers)
{
realloc_span(len);
std::memcpy(&m_span[0], covers, len * sizeof(cover_type));
}
public:
pixfmt_amask_adaptor(pixfmt_type& pixf, amask_type& mask) :
m_pixf(&pixf), m_mask(&mask), m_span()
{}
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
void attach_alpha_mask(amask_type& mask) { m_mask = &mask; }
//--------------------------------------------------------------------
template<class PixFmt2>
bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
{
return m_pixf->attach(pixf, x1, y1, x2, y2);
}
//--------------------------------------------------------------------
unsigned width() const { return m_pixf->width(); }
unsigned height() const { return m_pixf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
return m_pixf->pixel(x, y);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y));
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
}
//--------------------------------------------------------------------
void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
realloc_span(len);
m_mask->fill_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y,
unsigned len,
const color_type& c,
cover_type)
{
init_span(len);
m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y,
unsigned len,
const color_type& c)
{
realloc_span(len);
m_mask->fill_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void blend_vline(int x, int y,
unsigned len,
const color_type& c,
cover_type)
{
init_span(len);
m_mask->combine_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const cover_type* covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const cover_type* covers)
{
init_span(len, covers);
m_mask->combine_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
{
realloc_span(len);
m_mask->fill_hspan(x, y, &m_span[0], len);
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
{
realloc_span(len);
m_mask->fill_vspan(x, y, &m_span[0], len);
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
if(covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, &m_span[0], len);
}
else
{
realloc_span(len);
m_mask->fill_hspan(x, y, &m_span[0], len);
}
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
if(covers)
{
init_span(len, covers);
m_mask->combine_vspan(x, y, &m_span[0], len);
}
else
{
realloc_span(len);
m_mask->fill_vspan(x, y, &m_span[0], len);
}
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
}
private:
pixfmt_type* m_pixf;
const amask_type* m_mask;
pod_array<cover_type> m_span;
};
}
#endif

View File

@@ -0,0 +1,97 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_BASE_INCLUDED
#define AGG_PIXFMT_BASE_INCLUDED
#include "agg_basics.h"
#include "agg_color_gray.h"
#include "agg_color_rgba.h"
namespace agg
{
struct pixfmt_gray_tag
{
};
struct pixfmt_rgb_tag
{
};
struct pixfmt_rgba_tag
{
};
//--------------------------------------------------------------blender_base
template<class ColorT, class Order = void>
struct blender_base
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
static rgba get(value_type r, value_type g, value_type b, value_type a, cover_type cover = cover_full)
{
if (cover > cover_none)
{
rgba c(
color_type::to_double(r),
color_type::to_double(g),
color_type::to_double(b),
color_type::to_double(a));
if (cover < cover_full)
{
double x = double(cover) / cover_full;
c.r *= x;
c.g *= x;
c.b *= x;
c.a *= x;
}
return c;
}
else return rgba::no_color();
}
static rgba get(const value_type* p, cover_type cover = cover_full)
{
return get(
p[order_type::R],
p[order_type::G],
p[order_type::B],
p[order_type::A],
cover);
}
static void set(value_type* p, value_type r, value_type g, value_type b, value_type a)
{
p[order_type::R] = r;
p[order_type::G] = g;
p[order_type::B] = b;
p[order_type::A] = a;
}
static void set(value_type* p, const rgba& c)
{
p[order_type::R] = color_type::from_double(c.r);
p[order_type::G] = color_type::from_double(c.g);
p[order_type::B] = color_type::from_double(c.b);
p[order_type::A] = color_type::from_double(c.a);
}
};
}
#endif

View File

@@ -0,0 +1,738 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for high precision colors has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com
//
// Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers.
//
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_GRAY_INCLUDED
#define AGG_PIXFMT_GRAY_INCLUDED
#include <cstring>
#include "agg_pixfmt_base.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//============================================================blender_gray
template<class ColorT> struct blender_gray
{
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
typedef typename color_type::long_type long_type;
// Blend pixels using the non-premultiplied form of Alvy-Ray Smith's
// compositing function. Since the render buffer is opaque we skip the
// initial premultiply and final demultiply.
static AGG_INLINE void blend_pix(value_type* p,
value_type cv, value_type alpha, cover_type cover)
{
blend_pix(p, cv, color_type::mult_cover(alpha, cover));
}
static AGG_INLINE void blend_pix(value_type* p,
value_type cv, value_type alpha)
{
*p = color_type::lerp(*p, cv, alpha);
}
};
//======================================================blender_gray_pre
template<class ColorT> struct blender_gray_pre
{
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
typedef typename color_type::long_type long_type;
// Blend pixels using the premultiplied form of Alvy-Ray Smith's
// compositing function.
static AGG_INLINE void blend_pix(value_type* p,
value_type cv, value_type alpha, cover_type cover)
{
blend_pix(p, color_type::mult_cover(cv, cover), color_type::mult_cover(alpha, cover));
}
static AGG_INLINE void blend_pix(value_type* p,
value_type cv, value_type alpha)
{
*p = color_type::prelerp(*p, cv, alpha);
}
};
//=====================================================apply_gamma_dir_gray
template<class ColorT, class GammaLut> class apply_gamma_dir_gray
{
public:
typedef typename ColorT::value_type value_type;
apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {}
AGG_INLINE void operator () (value_type* p)
{
*p = m_gamma.dir(*p);
}
private:
const GammaLut& m_gamma;
};
//=====================================================apply_gamma_inv_gray
template<class ColorT, class GammaLut> class apply_gamma_inv_gray
{
public:
typedef typename ColorT::value_type value_type;
apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {}
AGG_INLINE void operator () (value_type* p)
{
*p = m_gamma.inv(*p);
}
private:
const GammaLut& m_gamma;
};
//=================================================pixfmt_alpha_blend_gray
template<class Blender, class RenBuf, unsigned Step = 1, unsigned Offset = 0>
class pixfmt_alpha_blend_gray
{
public:
typedef pixfmt_gray_tag pixfmt_category;
typedef RenBuf rbuf_type;
typedef typename rbuf_type::row_data row_data;
typedef Blender blender_type;
typedef typename blender_type::color_type color_type;
typedef int order_type; // A fake one
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
enum
{
num_components = 1,
pix_width = sizeof(value_type) * Step,
pix_step = Step,
pix_offset = Offset,
};
struct pixel_type
{
value_type c[num_components];
void set(value_type v)
{
c[0] = v;
}
void set(const color_type& color)
{
set(color.v);
}
void get(value_type& v) const
{
v = c[0];
}
color_type get() const
{
return color_type(c[0]);
}
pixel_type* next()
{
return (pixel_type*)(c + pix_step);
}
const pixel_type* next() const
{
return (const pixel_type*)(c + pix_step);
}
pixel_type* advance(int n)
{
return (pixel_type*)(c + n * pix_step);
}
const pixel_type* advance(int n) const
{
return (const pixel_type*)(c + n * pix_step);
}
};
private:
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(pixel_type* p,
value_type v, value_type a,
unsigned cover)
{
blender_type::blend_pix(p->c, v, a, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(pixel_type* p, value_type v, value_type a)
{
blender_type::blend_pix(p->c, v, a);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover)
{
blender_type::blend_pix(p->c, c.v, c.a, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(pixel_type* p, const color_type& c)
{
blender_type::blend_pix(p->c, c.v, c.a);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
{
if (!c.is_transparent())
{
if (c.is_opaque() && cover == cover_mask)
{
p->set(c);
}
else
{
blend_pix(p, c, cover);
}
}
}
//--------------------------------------------------------------------
AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
{
if (!c.is_transparent())
{
if (c.is_opaque())
{
p->set(c);
}
else
{
blend_pix(p, c);
}
}
}
public:
//--------------------------------------------------------------------
explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
m_rbuf(&rb)
{}
void attach(rbuf_type& rb) { m_rbuf = &rb; }
//--------------------------------------------------------------------
template<class PixFmt>
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
{
rect_i r(x1, y1, x2, y2);
if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
{
int stride = pixf.stride();
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
(r.x2 - r.x1) + 1,
(r.y2 - r.y1) + 1,
stride);
return true;
}
return false;
}
//--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
AGG_INLINE int stride() const { return m_rbuf->stride(); }
//--------------------------------------------------------------------
int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
row_data row(int y) const { return m_rbuf->row(y); }
//--------------------------------------------------------------------
AGG_INLINE int8u* pix_ptr(int x, int y)
{
return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
}
AGG_INLINE const int8u* pix_ptr(int x, int y) const
{
return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
}
// Return pointer to pixel value, forcing row to be allocated.
AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len)
{
return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset));
}
// Return pointer to pixel value, or null if row not allocated.
AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const
{
int8u* p = m_rbuf->row_ptr(y);
return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0;
}
// Get pixel pointer from raw buffer pointer.
AGG_INLINE static pixel_type* pix_value_ptr(void* p)
{
return (pixel_type*)((value_type*)p + pix_offset);
}
// Get pixel pointer from raw buffer pointer.
AGG_INLINE static const pixel_type* pix_value_ptr(const void* p)
{
return (const pixel_type*)((const value_type*)p + pix_offset);
}
//--------------------------------------------------------------------
AGG_INLINE static void write_plain_color(void* p, color_type c)
{
// Grayscale formats are implicitly premultiplied.
c.premultiply();
pix_value_ptr(p)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE static color_type read_plain_color(const void* p)
{
return pix_value_ptr(p)->get();
}
//--------------------------------------------------------------------
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
{
((pixel_type*)p)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE color_type pixel(int x, int y) const
{
if (const pixel_type* p = pix_value_ptr(x, y))
{
return p->get();
}
return color_type::no_color();
}
//--------------------------------------------------------------------
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
{
pix_value_ptr(x, y, 1)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
pixel_type* p = pix_value_ptr(x, y, len);
do
{
p->set(c);
p = p->next();
}
while(--len);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_vline(int x, int y,
unsigned len,
const color_type& c)
{
do
{
pix_value_ptr(x, y++, 1)->set(c);
}
while (--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
if (!c.is_transparent())
{
pixel_type* p = pix_value_ptr(x, y, len);
if (c.is_opaque() && cover == cover_mask)
{
do
{
p->set(c);
p = p->next();
}
while (--len);
}
else
{
do
{
blend_pix(p, c, cover);
p = p->next();
}
while (--len);
}
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
if (!c.is_transparent())
{
if (c.is_opaque() && cover == cover_mask)
{
do
{
pix_value_ptr(x, y++, 1)->set(c);
}
while (--len);
}
else
{
do
{
blend_pix(pix_value_ptr(x, y++, 1), c, cover);
}
while (--len);
}
}
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
if (!c.is_transparent())
{
pixel_type* p = pix_value_ptr(x, y, len);
do
{
if (c.is_opaque() && *covers == cover_mask)
{
p->set(c);
}
else
{
blend_pix(p, c, *covers);
}
p = p->next();
++covers;
}
while (--len);
}
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
if (!c.is_transparent())
{
do
{
pixel_type* p = pix_value_ptr(x, y++, 1);
if (c.is_opaque() && *covers == cover_mask)
{
p->set(c);
}
else
{
blend_pix(p, c, *covers);
}
++covers;
}
while (--len);
}
}
//--------------------------------------------------------------------
void copy_color_hspan(int x, int y,
unsigned len,
const color_type* colors)
{
pixel_type* p = pix_value_ptr(x, y, len);
do
{
p->set(*colors++);
p = p->next();
}
while (--len);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
do
{
pix_value_ptr(x, y++, 1)->set(*colors++);
}
while (--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
pixel_type* p = pix_value_ptr(x, y, len);
if (covers)
{
do
{
copy_or_blend_pix(p, *colors++, *covers++);
p = p->next();
}
while (--len);
}
else
{
if (cover == cover_mask)
{
do
{
copy_or_blend_pix(p, *colors++);
p = p->next();
}
while (--len);
}
else
{
do
{
copy_or_blend_pix(p, *colors++, cover);
p = p->next();
}
while (--len);
}
}
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
if (covers)
{
do
{
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
}
while (--len);
}
else
{
if (cover == cover_mask)
{
do
{
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
}
while (--len);
}
else
{
do
{
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
}
while (--len);
}
}
}
//--------------------------------------------------------------------
template<class Function> void for_each_pixel(Function f)
{
unsigned y;
for (y = 0; y < height(); ++y)
{
row_data r = m_rbuf->row(y);
if (r.ptr)
{
unsigned len = r.x2 - r.x1 + 1;
pixel_type* p = pix_value_ptr(r.x1, y, len);
do
{
f(p->c);
p = p->next();
}
while (--len);
}
}
}
//--------------------------------------------------------------------
template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
{
for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g));
}
//--------------------------------------------------------------------
template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
{
for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g));
}
//--------------------------------------------------------------------
template<class RenBuf2>
void copy_from(const RenBuf2& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
if (const int8u* p = from.row_ptr(ysrc))
{
std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
p + xsrc * pix_width,
len * pix_width);
}
}
//--------------------------------------------------------------------
// Blend from single color, using grayscale surface as alpha channel.
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& from,
const color_type& color,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
typedef typename SrcPixelFormatRenderer::color_type src_color_type;
if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
{
pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
do
{
copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0]));
psrc = psrc->next();
pdst = pdst->next();
}
while (--len);
}
}
//--------------------------------------------------------------------
// Blend from color table, using grayscale surface as indexes into table.
// Obviously, this only works for integer value types.
template<class SrcPixelFormatRenderer>
void blend_from_lut(const SrcPixelFormatRenderer& from,
const color_type* color_lut,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
{
pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
do
{
copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
psrc = psrc->next();
pdst = pdst->next();
}
while (--len);
}
}
private:
rbuf_type* m_rbuf;
};
typedef blender_gray<gray8> blender_gray8;
typedef blender_gray<sgray8> blender_sgray8;
typedef blender_gray<gray16> blender_gray16;
typedef blender_gray<gray32> blender_gray32;
typedef blender_gray_pre<gray8> blender_gray8_pre;
typedef blender_gray_pre<sgray8> blender_sgray8_pre;
typedef blender_gray_pre<gray16> blender_gray16_pre;
typedef blender_gray_pre<gray32> blender_gray32_pre;
typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8;
typedef pixfmt_alpha_blend_gray<blender_sgray8, rendering_buffer> pixfmt_sgray8;
typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16;
typedef pixfmt_alpha_blend_gray<blender_gray32, rendering_buffer> pixfmt_gray32;
typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre;
typedef pixfmt_alpha_blend_gray<blender_sgray8_pre, rendering_buffer> pixfmt_sgray8_pre;
typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre;
typedef pixfmt_alpha_blend_gray<blender_gray32_pre, rendering_buffer> pixfmt_gray32_pre;
}
#endif

View File

@@ -0,0 +1,995 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for high precision colors has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com
//
// Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers.
//
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGB_INCLUDED
#define AGG_PIXFMT_RGB_INCLUDED
#include <cstring>
#include "agg_pixfmt_base.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//=====================================================apply_gamma_dir_rgb
template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb
{
public:
typedef typename ColorT::value_type value_type;
apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
AGG_INLINE void operator () (value_type* p)
{
p[Order::R] = m_gamma.dir(p[Order::R]);
p[Order::G] = m_gamma.dir(p[Order::G]);
p[Order::B] = m_gamma.dir(p[Order::B]);
}
private:
const GammaLut& m_gamma;
};
//=====================================================apply_gamma_inv_rgb
template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb
{
public:
typedef typename ColorT::value_type value_type;
apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
AGG_INLINE void operator () (value_type* p)
{
p[Order::R] = m_gamma.inv(p[Order::R]);
p[Order::G] = m_gamma.inv(p[Order::G]);
p[Order::B] = m_gamma.inv(p[Order::B]);
}
private:
const GammaLut& m_gamma;
};
//=========================================================blender_rgb
template<class ColorT, class Order>
struct blender_rgb
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
typedef typename color_type::long_type long_type;
// Blend pixels using the non-premultiplied form of Alvy-Ray Smith's
// compositing function. Since the render buffer is opaque we skip the
// initial premultiply and final demultiply.
//--------------------------------------------------------------------
static AGG_INLINE void blend_pix(value_type* p,
value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
{
blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
}
//--------------------------------------------------------------------
static AGG_INLINE void blend_pix(value_type* p,
value_type cr, value_type cg, value_type cb, value_type alpha)
{
p[Order::R] = color_type::lerp(p[Order::R], cr, alpha);
p[Order::G] = color_type::lerp(p[Order::G], cg, alpha);
p[Order::B] = color_type::lerp(p[Order::B], cb, alpha);
}
};
//======================================================blender_rgb_pre
template<class ColorT, class Order>
struct blender_rgb_pre
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
typedef typename color_type::long_type long_type;
// Blend pixels using the premultiplied form of Alvy-Ray Smith's
// compositing function.
//--------------------------------------------------------------------
static AGG_INLINE void blend_pix(value_type* p,
value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
{
blend_pix(p,
color_type::mult_cover(cr, cover),
color_type::mult_cover(cg, cover),
color_type::mult_cover(cb, cover),
color_type::mult_cover(alpha, cover));
}
//--------------------------------------------------------------------
static AGG_INLINE void blend_pix(value_type* p,
value_type cr, value_type cg, value_type cb, value_type alpha)
{
p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha);
p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha);
p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha);
}
};
//===================================================blender_rgb_gamma
template<class ColorT, class Order, class Gamma>
class blender_rgb_gamma : public blender_base<ColorT, Order>
{
public:
typedef ColorT color_type;
typedef Order order_type;
typedef Gamma gamma_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
typedef typename color_type::long_type long_type;
//--------------------------------------------------------------------
blender_rgb_gamma() : m_gamma(0) {}
void gamma(const gamma_type& g) { m_gamma = &g; }
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(value_type* p,
value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
{
blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(value_type* p,
value_type cr, value_type cg, value_type cb, value_type alpha)
{
calc_type r = m_gamma->dir(p[Order::R]);
calc_type g = m_gamma->dir(p[Order::G]);
calc_type b = m_gamma->dir(p[Order::B]);
p[Order::R] = m_gamma->inv(color_type::downscale((m_gamma->dir(cr) - r) * alpha) + r);
p[Order::G] = m_gamma->inv(color_type::downscale((m_gamma->dir(cg) - g) * alpha) + g);
p[Order::B] = m_gamma->inv(color_type::downscale((m_gamma->dir(cb) - b) * alpha) + b);
}
private:
const gamma_type* m_gamma;
};
//==================================================pixfmt_alpha_blend_rgb
template<class Blender, class RenBuf, unsigned Step, unsigned Offset = 0>
class pixfmt_alpha_blend_rgb
{
public:
typedef pixfmt_rgb_tag pixfmt_category;
typedef RenBuf rbuf_type;
typedef Blender blender_type;
typedef typename rbuf_type::row_data row_data;
typedef typename blender_type::color_type color_type;
typedef typename blender_type::order_type order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
enum
{
num_components = 3,
pix_step = Step,
pix_offset = Offset,
pix_width = sizeof(value_type) * pix_step
};
struct pixel_type
{
value_type c[num_components];
void set(value_type r, value_type g, value_type b)
{
c[order_type::R] = r;
c[order_type::G] = g;
c[order_type::B] = b;
}
void set(const color_type& color)
{
set(color.r, color.g, color.b);
}
void get(value_type& r, value_type& g, value_type& b) const
{
r = c[order_type::R];
g = c[order_type::G];
b = c[order_type::B];
}
color_type get() const
{
return color_type(
c[order_type::R],
c[order_type::G],
c[order_type::B]);
}
pixel_type* next()
{
return (pixel_type*)(c + pix_step);
}
const pixel_type* next() const
{
return (const pixel_type*)(c + pix_step);
}
pixel_type* advance(int n)
{
return (pixel_type*)(c + n * pix_step);
}
const pixel_type* advance(int n) const
{
return (const pixel_type*)(c + n * pix_step);
}
};
private:
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(pixel_type* p,
value_type r, value_type g, value_type b, value_type a,
unsigned cover)
{
m_blender.blend_pix(p->c, r, g, b, a, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(pixel_type* p,
value_type r, value_type g, value_type b, value_type a)
{
m_blender.blend_pix(p->c, r, g, b, a);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover)
{
m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(pixel_type* p, const color_type& c)
{
m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
{
if (!c.is_transparent())
{
if (c.is_opaque() && cover == cover_mask)
{
p->set(c);
}
else
{
blend_pix(p, c, cover);
}
}
}
//--------------------------------------------------------------------
AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
{
if (!c.is_transparent())
{
if (c.is_opaque())
{
p->set(c);
}
else
{
blend_pix(p, c);
}
}
}
public:
//--------------------------------------------------------------------
explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
m_rbuf(&rb)
{}
void attach(rbuf_type& rb) { m_rbuf = &rb; }
//--------------------------------------------------------------------
template<class PixFmt>
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
{
rect_i r(x1, y1, x2, y2);
if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
{
int stride = pixf.stride();
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
(r.x2 - r.x1) + 1,
(r.y2 - r.y1) + 1,
stride);
return true;
}
return false;
}
//--------------------------------------------------------------------
Blender& blender() { return m_blender; }
//--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
AGG_INLINE int stride() const { return m_rbuf->stride(); }
//--------------------------------------------------------------------
AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
//--------------------------------------------------------------------
AGG_INLINE int8u* pix_ptr(int x, int y)
{
return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
}
AGG_INLINE const int8u* pix_ptr(int x, int y) const
{
return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
}
// Return pointer to pixel value, forcing row to be allocated.
AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len)
{
return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset));
}
// Return pointer to pixel value, or null if row not allocated.
AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const
{
int8u* p = m_rbuf->row_ptr(y);
return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0;
}
// Get pixel pointer from raw buffer pointer.
AGG_INLINE static pixel_type* pix_value_ptr(void* p)
{
return (pixel_type*)((value_type*)p + pix_offset);
}
// Get pixel pointer from raw buffer pointer.
AGG_INLINE static const pixel_type* pix_value_ptr(const void* p)
{
return (const pixel_type*)((const value_type*)p + pix_offset);
}
//--------------------------------------------------------------------
AGG_INLINE static void write_plain_color(void* p, color_type c)
{
// RGB formats are implicitly premultiplied.
c.premultiply();
pix_value_ptr(p)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE static color_type read_plain_color(const void* p)
{
return pix_value_ptr(p)->get();
}
//--------------------------------------------------------------------
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
{
((pixel_type*)p)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE color_type pixel(int x, int y) const
{
if (const pixel_type* p = pix_value_ptr(x, y))
{
return p->get();
}
return color_type::no_color();
}
//--------------------------------------------------------------------
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
{
pix_value_ptr(x, y, 1)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
pixel_type* p = pix_value_ptr(x, y, len);
do
{
p->set(c);
p = p->next();
}
while(--len);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_vline(int x, int y,
unsigned len,
const color_type& c)
{
do
{
pix_value_ptr(x, y++, 1)->set(c);
}
while (--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
if (!c.is_transparent())
{
pixel_type* p = pix_value_ptr(x, y, len);
if (c.is_opaque() && cover == cover_mask)
{
do
{
p->set(c);
p = p->next();
}
while (--len);
}
else
{
do
{
blend_pix(p, c, cover);
p = p->next();
}
while (--len);
}
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
if (!c.is_transparent())
{
if (c.is_opaque() && cover == cover_mask)
{
do
{
pix_value_ptr(x, y++, 1)->set(c);
}
while (--len);
}
else
{
do
{
blend_pix(pix_value_ptr(x, y++, 1), c, cover);
}
while (--len);
}
}
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
if (!c.is_transparent())
{
pixel_type* p = pix_value_ptr(x, y, len);
do
{
if (c.is_opaque() && *covers == cover_mask)
{
p->set(c);
}
else
{
blend_pix(p, c, *covers);
}
p = p->next();
++covers;
}
while (--len);
}
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
if (!c.is_transparent())
{
do
{
pixel_type* p = pix_value_ptr(x, y++, 1);
if (c.is_opaque() && *covers == cover_mask)
{
p->set(c);
}
else
{
blend_pix(p, c, *covers);
}
++covers;
}
while (--len);
}
}
//--------------------------------------------------------------------
void copy_color_hspan(int x, int y,
unsigned len,
const color_type* colors)
{
pixel_type* p = pix_value_ptr(x, y, len);
do
{
p->set(*colors++);
p = p->next();
}
while (--len);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
do
{
pix_value_ptr(x, y++, 1)->set(*colors++);
}
while (--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
pixel_type* p = pix_value_ptr(x, y, len);
if (covers)
{
do
{
copy_or_blend_pix(p, *colors++, *covers++);
p = p->next();
}
while (--len);
}
else
{
if (cover == cover_mask)
{
do
{
copy_or_blend_pix(p, *colors++);
p = p->next();
}
while (--len);
}
else
{
do
{
copy_or_blend_pix(p, *colors++, cover);
p = p->next();
}
while (--len);
}
}
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
if (covers)
{
do
{
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
}
while (--len);
}
else
{
if (cover == cover_mask)
{
do
{
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
}
while (--len);
}
else
{
do
{
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
}
while (--len);
}
}
}
//--------------------------------------------------------------------
template<class Function> void for_each_pixel(Function f)
{
for (unsigned y = 0; y < height(); ++y)
{
row_data r = m_rbuf->row(y);
if (r.ptr)
{
unsigned len = r.x2 - r.x1 + 1;
pixel_type* p = pix_value_ptr(r.x1, y, len);
do
{
f(p->c);
p = p->next();
}
while (--len);
}
}
}
//--------------------------------------------------------------------
template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
{
for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g));
}
//--------------------------------------------------------------------
template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
{
for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g));
}
//--------------------------------------------------------------------
template<class RenBuf2>
void copy_from(const RenBuf2& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
if (const int8u* p = from.row_ptr(ysrc))
{
std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
p + xsrc * pix_width,
len * pix_width);
}
}
//--------------------------------------------------------------------
// Blend from an RGBA surface.
template<class SrcPixelFormatRenderer>
void blend_from(const SrcPixelFormatRenderer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
typedef typename SrcPixelFormatRenderer::order_type src_order;
if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
{
pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
if (cover == cover_mask)
{
do
{
value_type alpha = psrc->c[src_order::A];
if (alpha <= color_type::empty_value())
{
if (alpha >= color_type::full_value())
{
pdst->c[order_type::R] = psrc->c[src_order::R];
pdst->c[order_type::G] = psrc->c[src_order::G];
pdst->c[order_type::B] = psrc->c[src_order::B];
}
else
{
blend_pix(pdst,
psrc->c[src_order::R],
psrc->c[src_order::G],
psrc->c[src_order::B],
alpha);
}
}
psrc = psrc->next();
pdst = pdst->next();
}
while(--len);
}
else
{
do
{
copy_or_blend_pix(pdst, psrc->get(), cover);
psrc = psrc->next();
pdst = pdst->next();
}
while (--len);
}
}
}
//--------------------------------------------------------------------
// Blend from single color, using grayscale surface as alpha channel.
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& from,
const color_type& color,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
typedef typename SrcPixelFormatRenderer::color_type src_color_type;
if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
{
pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
do
{
copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0]));
psrc = psrc->next();
pdst = pdst->next();
}
while (--len);
}
}
//--------------------------------------------------------------------
// Blend from color table, using grayscale surface as indexes into table.
// Obviously, this only works for integer value types.
template<class SrcPixelFormatRenderer>
void blend_from_lut(const SrcPixelFormatRenderer& from,
const color_type* color_lut,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len,
int8u cover)
{
typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
{
pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
if (cover == cover_mask)
{
do
{
const color_type& color = color_lut[psrc->c[0]];
blend_pix(pdst, color);
psrc = psrc->next();
pdst = pdst->next();
}
while(--len);
}
else
{
do
{
copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
psrc = psrc->next();
pdst = pdst->next();
}
while(--len);
}
}
}
private:
rbuf_type* m_rbuf;
Blender m_blender;
};
//-----------------------------------------------------------------------
typedef blender_rgb<rgba8, order_rgb> blender_rgb24;
typedef blender_rgb<rgba8, order_bgr> blender_bgr24;
typedef blender_rgb<srgba8, order_rgb> blender_srgb24;
typedef blender_rgb<srgba8, order_bgr> blender_sbgr24;
typedef blender_rgb<rgba16, order_rgb> blender_rgb48;
typedef blender_rgb<rgba16, order_bgr> blender_bgr48;
typedef blender_rgb<rgba32, order_rgb> blender_rgb96;
typedef blender_rgb<rgba32, order_bgr> blender_bgr96;
typedef blender_rgb_pre<rgba8, order_rgb> blender_rgb24_pre;
typedef blender_rgb_pre<rgba8, order_bgr> blender_bgr24_pre;
typedef blender_rgb_pre<srgba8, order_rgb> blender_srgb24_pre;
typedef blender_rgb_pre<srgba8, order_bgr> blender_sbgr24_pre;
typedef blender_rgb_pre<rgba16, order_rgb> blender_rgb48_pre;
typedef blender_rgb_pre<rgba16, order_bgr> blender_bgr48_pre;
typedef blender_rgb_pre<rgba32, order_rgb> blender_rgb96_pre;
typedef blender_rgb_pre<rgba32, order_bgr> blender_bgr96_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 3> pixfmt_rgb24;
typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 3> pixfmt_bgr24;
typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 3> pixfmt_srgb24;
typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 3> pixfmt_sbgr24;
typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 3> pixfmt_rgb48;
typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 3> pixfmt_bgr48;
typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 3> pixfmt_rgb96;
typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 3> pixfmt_bgr96;
typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 3> pixfmt_rgb24_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 3> pixfmt_bgr24_pre;
typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 3> pixfmt_srgb24_pre;
typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 3> pixfmt_sbgr24_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 3> pixfmt_rgb48_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 3> pixfmt_bgr48_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 3> pixfmt_rgb96_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 3> pixfmt_bgr96_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 4, 0> pixfmt_rgbx32;
typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 4, 1> pixfmt_xrgb32;
typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 4, 1> pixfmt_xbgr32;
typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 4, 0> pixfmt_bgrx32;
typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 4, 0> pixfmt_srgbx32;
typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 4, 1> pixfmt_sxrgb32;
typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 4, 1> pixfmt_sxbgr32;
typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 4, 0> pixfmt_sbgrx32;
typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 4, 0> pixfmt_rgbx64;
typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 4, 1> pixfmt_xrgb64;
typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 4, 1> pixfmt_xbgr64;
typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 4, 0> pixfmt_bgrx64;
typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 4, 0> pixfmt_rgbx128;
typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 4, 1> pixfmt_xrgb128;
typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 4, 1> pixfmt_xbgr128;
typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 4, 0> pixfmt_bgrx128;
typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 4, 0> pixfmt_rgbx32_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 4, 1> pixfmt_xrgb32_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 4, 1> pixfmt_xbgr32_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 4, 0> pixfmt_bgrx32_pre;
typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 4, 0> pixfmt_srgbx32_pre;
typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 4, 1> pixfmt_sxrgb32_pre;
typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 4, 1> pixfmt_sxbgr32_pre;
typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 4, 0> pixfmt_sbgrx32_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 4, 0> pixfmt_rgbx64_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 4, 1> pixfmt_xrgb64_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 4, 1> pixfmt_xbgr64_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 4, 0> pixfmt_bgrx64_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 4, 0> pixfmt_rgbx128_pre;
typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 4, 1> pixfmt_xrgb128_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 4, 1> pixfmt_xbgr128_pre;
typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 4, 0> pixfmt_bgrx128_pre;
//-----------------------------------------------------pixfmt_rgb24_gamma
template<class Gamma> class pixfmt_rgb24_gamma :
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
};
//-----------------------------------------------------pixfmt_srgb24_gamma
template<class Gamma> class pixfmt_srgb24_gamma :
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_srgb24_gamma(rendering_buffer& rb, const Gamma& g) :
pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
};
//-----------------------------------------------------pixfmt_bgr24_gamma
template<class Gamma> class pixfmt_bgr24_gamma :
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
};
//-----------------------------------------------------pixfmt_sbgr24_gamma
template<class Gamma> class pixfmt_sbgr24_gamma :
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_sbgr24_gamma(rendering_buffer& rb, const Gamma& g) :
pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
};
//-----------------------------------------------------pixfmt_rgb48_gamma
template<class Gamma> class pixfmt_rgb48_gamma :
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
};
//-----------------------------------------------------pixfmt_bgr48_gamma
template<class Gamma> class pixfmt_bgr48_gamma :
public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
};
}
#endif

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,157 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_TRANSPOSER_INCLUDED
#define AGG_PIXFMT_TRANSPOSER_INCLUDED
#include "agg_basics.h"
namespace agg
{
//=======================================================pixfmt_transposer
template<class PixFmt> class pixfmt_transposer
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
//--------------------------------------------------------------------
pixfmt_transposer() : m_pixf(0) {}
explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {}
void attach(pixfmt_type& pixf) { m_pixf = &pixf; }
//--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_pixf->height(); }
AGG_INLINE unsigned height() const { return m_pixf->width(); }
//--------------------------------------------------------------------
AGG_INLINE color_type pixel(int x, int y) const
{
return m_pixf->pixel(y, x);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
{
m_pixf->copy_pixel(y, x, c);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pixel(int x, int y,
const color_type& c,
int8u cover)
{
m_pixf->blend_pixel(y, x, c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
m_pixf->copy_vline(y, x, len, c);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_vline(int x, int y,
unsigned len,
const color_type& c)
{
m_pixf->copy_hline(y, x, len, c);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_hline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
m_pixf->blend_vline(y, x, len, c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_vline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
m_pixf->blend_hline(y, x, len, c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
m_pixf->blend_solid_vspan(y, x, len, c, covers);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
m_pixf->blend_solid_hspan(y, x, len, c, covers);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_color_hspan(int x, int y,
unsigned len,
const color_type* colors)
{
m_pixf->copy_color_vspan(y, x, len, colors);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
m_pixf->copy_color_hspan(y, x, len, colors);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
m_pixf->blend_color_vspan(y, x, len, colors, covers, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
m_pixf->blend_color_hspan(y, x, len, colors, covers, cover);
}
private:
pixfmt_type* m_pixf;
};
}
#endif

View File

@@ -0,0 +1,742 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
//
// The author gratefully acknowleges the support of David Turner,
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
// libray - in producing this work. See http://www.freetype.org for details.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com
//
// Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers.
//
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED
#define AGG_RASTERIZER_CELLS_AA_INCLUDED
#include <cstring>
#include <cstdlib>
#include <limits>
#include "agg_math.h"
#include "agg_array.h"
namespace agg
{
//-----------------------------------------------------rasterizer_cells_aa
// An internal class that implements the main rasterization algorithm.
// Used in the rasterizer. Should not be used direcly.
template<class Cell> class rasterizer_cells_aa
{
enum cell_block_scale_e
{
cell_block_shift = 12,
cell_block_size = 1 << cell_block_shift,
cell_block_mask = cell_block_size - 1,
cell_block_pool = 256
};
struct sorted_y
{
unsigned start;
unsigned num;
};
public:
typedef Cell cell_type;
typedef rasterizer_cells_aa<Cell> self_type;
~rasterizer_cells_aa();
rasterizer_cells_aa(unsigned cell_block_limit=1024);
void reset();
void style(const cell_type& style_cell);
void line(int x1, int y1, int x2, int y2);
int min_x() const { return m_min_x; }
int min_y() const { return m_min_y; }
int max_x() const { return m_max_x; }
int max_y() const { return m_max_y; }
void sort_cells();
unsigned total_cells() const
{
return m_num_cells;
}
unsigned scanline_num_cells(unsigned y) const
{
return m_sorted_y[y - m_min_y].num;
}
const cell_type* const* scanline_cells(unsigned y) const
{
return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start;
}
bool sorted() const { return m_sorted; }
private:
rasterizer_cells_aa(const self_type&);
const self_type& operator = (const self_type&);
void set_curr_cell(int x, int y);
void add_curr_cell();
void render_hline(int ey, int x1, int y1, int x2, int y2);
void allocate_block();
private:
unsigned m_num_blocks;
unsigned m_max_blocks;
unsigned m_curr_block;
unsigned m_num_cells;
unsigned m_cell_block_limit;
cell_type** m_cells;
cell_type* m_curr_cell_ptr;
pod_vector<cell_type*> m_sorted_cells;
pod_vector<sorted_y> m_sorted_y;
cell_type m_curr_cell;
cell_type m_style_cell;
int m_min_x;
int m_min_y;
int m_max_x;
int m_max_y;
bool m_sorted;
};
//------------------------------------------------------------------------
template<class Cell>
rasterizer_cells_aa<Cell>::~rasterizer_cells_aa()
{
if(m_num_blocks)
{
cell_type** ptr = m_cells + m_num_blocks - 1;
while(m_num_blocks--)
{
pod_allocator<cell_type>::deallocate(*ptr, cell_block_size);
ptr--;
}
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
}
}
//------------------------------------------------------------------------
template<class Cell>
rasterizer_cells_aa<Cell>::rasterizer_cells_aa(unsigned cell_block_limit) :
m_num_blocks(0),
m_max_blocks(0),
m_curr_block(0),
m_num_cells(0),
m_cell_block_limit(cell_block_limit),
m_cells(0),
m_curr_cell_ptr(0),
m_sorted_cells(),
m_sorted_y(),
m_min_x(std::numeric_limits<int>::max()),
m_min_y(std::numeric_limits<int>::max()),
m_max_x(std::numeric_limits<int>::min()),
m_max_y(std::numeric_limits<int>::min()),
m_sorted(false)
{
m_style_cell.initial();
m_curr_cell.initial();
}
//------------------------------------------------------------------------
template<class Cell>
void rasterizer_cells_aa<Cell>::reset()
{
m_num_cells = 0;
m_curr_block = 0;
m_curr_cell.initial();
m_style_cell.initial();
m_sorted = false;
m_min_x = std::numeric_limits<int>::max();
m_min_y = std::numeric_limits<int>::max();
m_max_x = std::numeric_limits<int>::min();
m_max_y = std::numeric_limits<int>::min();
}
//------------------------------------------------------------------------
template<class Cell>
AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell()
{
if(m_curr_cell.area | m_curr_cell.cover)
{
if((m_num_cells & cell_block_mask) == 0)
{
if(m_num_blocks >= m_cell_block_limit) return;
allocate_block();
}
*m_curr_cell_ptr++ = m_curr_cell;
++m_num_cells;
}
}
//------------------------------------------------------------------------
template<class Cell>
AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y)
{
if(m_curr_cell.not_equal(x, y, m_style_cell))
{
add_curr_cell();
m_curr_cell.style(m_style_cell);
m_curr_cell.x = x;
m_curr_cell.y = y;
m_curr_cell.cover = 0;
m_curr_cell.area = 0;
}
}
//------------------------------------------------------------------------
template<class Cell>
AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey,
int x1, int y1,
int x2, int y2)
{
int ex1 = x1 >> poly_subpixel_shift;
int ex2 = x2 >> poly_subpixel_shift;
int fx1 = x1 & poly_subpixel_mask;
int fx2 = x2 & poly_subpixel_mask;
int delta, p, first;
long long dx;
int incr, lift, mod, rem;
//trivial case. Happens often
if(y1 == y2)
{
set_curr_cell(ex2, ey);
return;
}
//everything is located in a single cell. That is easy!
if(ex1 == ex2)
{
delta = y2 - y1;
m_curr_cell.cover += delta;
m_curr_cell.area += (fx1 + fx2) * delta;
return;
}
//ok, we'll have to render a run of adjacent cells on the same
//hline...
p = (poly_subpixel_scale - fx1) * (y2 - y1);
first = poly_subpixel_scale;
incr = 1;
dx = (long long)x2 - (long long)x1;
if(dx < 0)
{
p = fx1 * (y2 - y1);
first = 0;
incr = -1;
dx = -dx;
}
delta = (int)(p / dx);
mod = (int)(p % dx);
if(mod < 0)
{
delta--;
mod += dx;
}
m_curr_cell.cover += delta;
m_curr_cell.area += (fx1 + first) * delta;
ex1 += incr;
set_curr_cell(ex1, ey);
y1 += delta;
if(ex1 != ex2)
{
p = poly_subpixel_scale * (y2 - y1 + delta);
lift = (int)(p / dx);
rem = (int)(p % dx);
if (rem < 0)
{
lift--;
rem += dx;
}
mod -= dx;
while (ex1 != ex2)
{
delta = lift;
mod += rem;
if(mod >= 0)
{
mod -= dx;
delta++;
}
m_curr_cell.cover += delta;
m_curr_cell.area += poly_subpixel_scale * delta;
y1 += delta;
ex1 += incr;
set_curr_cell(ex1, ey);
}
}
delta = y2 - y1;
m_curr_cell.cover += delta;
m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta;
}
//------------------------------------------------------------------------
template<class Cell>
AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell)
{
m_style_cell.style(style_cell);
}
//------------------------------------------------------------------------
template<class Cell>
void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2)
{
enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };
long long dx = (long long)x2 - (long long)x1;
if(dx >= dx_limit || dx <= -dx_limit)
{
int cx = (int)(((long long)x1 + (long long)x2) >> 1);
int cy = (int)(((long long)y1 + (long long)y2) >> 1);
line(x1, y1, cx, cy);
line(cx, cy, x2, y2);
}
long long dy = (long long)y2 - (long long)y1;
int ex1 = x1 >> poly_subpixel_shift;
int ex2 = x2 >> poly_subpixel_shift;
int ey1 = y1 >> poly_subpixel_shift;
int ey2 = y2 >> poly_subpixel_shift;
int fy1 = y1 & poly_subpixel_mask;
int fy2 = y2 & poly_subpixel_mask;
int x_from, x_to;
int rem, mod, lift, delta, first, incr;
long long p;
if(ex1 < m_min_x) m_min_x = ex1;
if(ex1 > m_max_x) m_max_x = ex1;
if(ey1 < m_min_y) m_min_y = ey1;
if(ey1 > m_max_y) m_max_y = ey1;
if(ex2 < m_min_x) m_min_x = ex2;
if(ex2 > m_max_x) m_max_x = ex2;
if(ey2 < m_min_y) m_min_y = ey2;
if(ey2 > m_max_y) m_max_y = ey2;
set_curr_cell(ex1, ey1);
//everything is on a single hline
if(ey1 == ey2)
{
render_hline(ey1, x1, fy1, x2, fy2);
return;
}
//Vertical line - we have to calculate start and end cells,
//and then - the common values of the area and coverage for
//all cells of the line. We know exactly there's only one
//cell, so, we don't have to call render_hline().
incr = 1;
if(dx == 0)
{
int ex = x1 >> poly_subpixel_shift;
int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1;
int area;
first = poly_subpixel_scale;
if(dy < 0)
{
first = 0;
incr = -1;
}
x_from = x1;
//render_hline(ey1, x_from, fy1, x_from, first);
delta = first - fy1;
m_curr_cell.cover += delta;
m_curr_cell.area += two_fx * delta;
ey1 += incr;
set_curr_cell(ex, ey1);
delta = first + first - poly_subpixel_scale;
area = two_fx * delta;
while(ey1 != ey2)
{
//render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first);
m_curr_cell.cover = delta;
m_curr_cell.area = area;
ey1 += incr;
set_curr_cell(ex, ey1);
}
//render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2);
delta = fy2 - poly_subpixel_scale + first;
m_curr_cell.cover += delta;
m_curr_cell.area += two_fx * delta;
return;
}
//ok, we have to render several hlines
p = (poly_subpixel_scale - fy1) * dx;
first = poly_subpixel_scale;
if(dy < 0)
{
p = fy1 * dx;
first = 0;
incr = -1;
dy = -dy;
}
delta = (int)(p / dy);
mod = (int)(p % dy);
if(mod < 0)
{
delta--;
mod += dy;
}
x_from = x1 + delta;
render_hline(ey1, x1, fy1, x_from, first);
ey1 += incr;
set_curr_cell(x_from >> poly_subpixel_shift, ey1);
if(ey1 != ey2)
{
p = poly_subpixel_scale * dx;
lift = (int)(p / dy);
rem = (int)(p % dy);
if(rem < 0)
{
lift--;
rem += dy;
}
mod -= dy;
while(ey1 != ey2)
{
delta = lift;
mod += rem;
if (mod >= 0)
{
mod -= dy;
delta++;
}
x_to = x_from + delta;
render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first);
x_from = x_to;
ey1 += incr;
set_curr_cell(x_from >> poly_subpixel_shift, ey1);
}
}
render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2);
}
//------------------------------------------------------------------------
template<class Cell>
void rasterizer_cells_aa<Cell>::allocate_block()
{
if(m_curr_block >= m_num_blocks)
{
if(m_num_blocks >= m_max_blocks)
{
cell_type** new_cells =
pod_allocator<cell_type*>::allocate(m_max_blocks +
cell_block_pool);
if(m_cells)
{
std::memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*));
pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks);
}
m_cells = new_cells;
m_max_blocks += cell_block_pool;
}
m_cells[m_num_blocks++] =
pod_allocator<cell_type>::allocate(cell_block_size);
}
m_curr_cell_ptr = m_cells[m_curr_block++];
}
//------------------------------------------------------------------------
template <class T> static AGG_INLINE void swap_cells(T* a, T* b)
{
T temp = *a;
*a = *b;
*b = temp;
}
//------------------------------------------------------------------------
enum
{
qsort_threshold = 9
};
//------------------------------------------------------------------------
template<class Cell>
void qsort_cells(Cell** start, unsigned num)
{
Cell** stack[80];
Cell*** top;
Cell** limit;
Cell** base;
limit = start + num;
base = start;
top = stack;
for (;;)
{
int len = int(limit - base);
Cell** i;
Cell** j;
Cell** pivot;
if(len > qsort_threshold)
{
// we use base + len/2 as the pivot
pivot = base + len / 2;
swap_cells(base, pivot);
i = base + 1;
j = limit - 1;
// now ensure that *i <= *base <= *j
if((*j)->x < (*i)->x)
{
swap_cells(i, j);
}
if((*base)->x < (*i)->x)
{
swap_cells(base, i);
}
if((*j)->x < (*base)->x)
{
swap_cells(base, j);
}
for(;;)
{
int x = (*base)->x;
do i++; while( (*i)->x < x );
do j--; while( x < (*j)->x );
if(i > j)
{
break;
}
swap_cells(i, j);
}
swap_cells(base, j);
// now, push the largest sub-array
if(j - base > limit - i)
{
top[0] = base;
top[1] = j;
base = i;
}
else
{
top[0] = i;
top[1] = limit;
limit = j;
}
top += 2;
}
else
{
// the sub-array is small, perform insertion sort
j = base;
i = j + 1;
for(; i < limit; j = i, i++)
{
for(; j[1]->x < (*j)->x; j--)
{
swap_cells(j + 1, j);
if (j == base)
{
break;
}
}
}
if(top > stack)
{
top -= 2;
base = top[0];
limit = top[1];
}
else
{
break;
}
}
}
}
//------------------------------------------------------------------------
template<class Cell>
void rasterizer_cells_aa<Cell>::sort_cells()
{
if(m_sorted) return; //Perform sort only the first time.
add_curr_cell();
m_curr_cell.x = std::numeric_limits<int>::max();
m_curr_cell.y = std::numeric_limits<int>::max();
m_curr_cell.cover = 0;
m_curr_cell.area = 0;
if(m_num_cells == 0) return;
// DBG: Check to see if min/max works well.
//for(unsigned nc = 0; nc < m_num_cells; nc++)
//{
// cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask);
// if(cell->x < m_min_x ||
// cell->y < m_min_y ||
// cell->x > m_max_x ||
// cell->y > m_max_y)
// {
// cell = cell; // Breakpoint here
// }
//}
// Allocate the array of cell pointers
m_sorted_cells.allocate(m_num_cells, 16);
// Allocate and zero the Y array
m_sorted_y.allocate(m_max_y - m_min_y + 1, 16);
m_sorted_y.zero();
// Create the Y-histogram (count the numbers of cells for each Y)
cell_type** block_ptr = m_cells;
cell_type* cell_ptr;
unsigned nb = m_num_cells;
unsigned i;
while(nb)
{
cell_ptr = *block_ptr++;
i = (nb > cell_block_size) ? unsigned(cell_block_size) : nb;
nb -= i;
while(i--)
{
m_sorted_y[cell_ptr->y - m_min_y].start++;
++cell_ptr;
}
}
// Convert the Y-histogram into the array of starting indexes
unsigned start = 0;
for(i = 0; i < m_sorted_y.size(); i++)
{
unsigned v = m_sorted_y[i].start;
m_sorted_y[i].start = start;
start += v;
}
// Fill the cell pointer array sorted by Y
block_ptr = m_cells;
nb = m_num_cells;
while(nb)
{
cell_ptr = *block_ptr++;
i = (nb > cell_block_size) ? unsigned(cell_block_size) : nb;
nb -= i;
while(i--)
{
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
++curr_y.num;
++cell_ptr;
}
}
// Finally arrange the X-arrays
for(i = 0; i < m_sorted_y.size(); i++)
{
const sorted_y& curr_y = m_sorted_y[i];
if(curr_y.num)
{
qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num);
}
}
m_sorted = true;
}
//------------------------------------------------------scanline_hit_test
class scanline_hit_test
{
public:
scanline_hit_test(int x) : m_x(x), m_hit(false) {}
void reset_spans() {}
void finalize(int) {}
void add_cell(int x, int)
{
if(m_x == x) m_hit = true;
}
void add_span(int x, int len, int)
{
if(m_x >= x && m_x < x+len) m_hit = true;
}
unsigned num_spans() const { return 1; }
bool hit() const { return m_hit; }
private:
int m_x;
bool m_hit;
};
}
#endif

View File

@@ -0,0 +1,665 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.3
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
//
// The author gratefully acknowleges the support of David Turner,
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
// libray - in producing this work. See http://www.freetype.org for details.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com
//
// Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers.
//
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED
#define AGG_RASTERIZER_COMPOUND_AA_INCLUDED
#include <limits>
#include "agg_rasterizer_cells_aa.h"
#include "agg_rasterizer_sl_clip.h"
namespace agg
{
//-----------------------------------------------------------cell_style_aa
// A pixel cell. There're no constructors defined and it was done
// intentionally in order to avoid extra overhead when allocating an
// array of cells.
struct cell_style_aa
{
int x;
int y;
int cover;
int area;
int16 left, right;
void initial()
{
x = std::numeric_limits<int>::max();
y = std::numeric_limits<int>::max();
cover = 0;
area = 0;
left = -1;
right = -1;
}
void style(const cell_style_aa& c)
{
left = c.left;
right = c.right;
}
int not_equal(int ex, int ey, const cell_style_aa& c) const
{
return ((unsigned)ex - (unsigned)x) | ((unsigned)ey - (unsigned)y) |
((unsigned)left - (unsigned)c.left) | ((unsigned)right - (unsigned)c.right);
}
};
//===========================================================layer_order_e
enum layer_order_e
{
layer_unsorted, //------layer_unsorted
layer_direct, //------layer_direct
layer_inverse //------layer_inverse
};
//==================================================rasterizer_compound_aa
template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa
{
struct style_info
{
unsigned start_cell;
unsigned num_cells;
int last_x;
};
struct cell_info
{
int x, area, cover;
};
public:
typedef Clip clip_type;
typedef typename Clip::conv_type conv_type;
typedef typename Clip::coord_type coord_type;
enum aa_scale_e
{
aa_shift = 8,
aa_scale = 1 << aa_shift,
aa_mask = aa_scale - 1,
aa_scale2 = aa_scale * 2,
aa_mask2 = aa_scale2 - 1
};
//--------------------------------------------------------------------
rasterizer_compound_aa() :
m_outline(),
m_clipper(),
m_filling_rule(fill_non_zero),
m_layer_order(layer_direct),
m_styles(), // Active Styles
m_ast(), // Active Style Table (unique values)
m_asm(), // Active Style Mask
m_cells(),
m_cover_buf(),
m_min_style(std::numeric_limits<int>::max()),
m_max_style(std::numeric_limits<int>::min()),
m_start_x(0),
m_start_y(0),
m_scan_y(std::numeric_limits<int>::max()),
m_sl_start(0),
m_sl_len(0)
{}
//--------------------------------------------------------------------
void reset();
void reset_clipping();
void clip_box(double x1, double y1, double x2, double y2);
void filling_rule(filling_rule_e filling_rule);
void layer_order(layer_order_e order);
//--------------------------------------------------------------------
void styles(int left, int right);
void move_to(int x, int y);
void line_to(int x, int y);
void move_to_d(double x, double y);
void line_to_d(double x, double y);
void add_vertex(double x, double y, unsigned cmd);
void edge(int x1, int y1, int x2, int y2);
void edge_d(double x1, double y1, double x2, double y2);
//-------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
if(m_outline.sorted()) reset();
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
}
//--------------------------------------------------------------------
int min_x() const { return m_outline.min_x(); }
int min_y() const { return m_outline.min_y(); }
int max_x() const { return m_outline.max_x(); }
int max_y() const { return m_outline.max_y(); }
int min_style() const { return m_min_style; }
int max_style() const { return m_max_style; }
//--------------------------------------------------------------------
void sort();
bool rewind_scanlines();
unsigned sweep_styles();
int scanline_start() const { return m_sl_start; }
unsigned scanline_length() const { return m_sl_len; }
unsigned style(unsigned style_idx) const;
cover_type* allocate_cover_buffer(unsigned len);
//--------------------------------------------------------------------
bool navigate_scanline(int y);
bool hit_test(int tx, int ty);
//--------------------------------------------------------------------
AGG_INLINE unsigned calculate_alpha(int area) const
{
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
if(cover < 0) cover = -cover;
if(m_filling_rule == fill_even_odd)
{
cover &= aa_mask2;
if(cover > aa_scale)
{
cover = aa_scale2 - cover;
}
}
if(cover > aa_mask) cover = aa_mask;
return cover;
}
//--------------------------------------------------------------------
// Sweeps one scanline with one style index. The style ID can be
// determined by calling style().
template<class Scanline> bool sweep_scanline(Scanline& sl, int style_idx)
{
int scan_y = m_scan_y - 1;
if(scan_y > m_outline.max_y()) return false;
sl.reset_spans();
if(style_idx < 0)
{
style_idx = 0;
}
else
{
style_idx++;
}
const style_info& st = m_styles[m_ast[style_idx]];
unsigned num_cells = st.num_cells;
cell_info* cell = &m_cells[st.start_cell];
int cover = 0;
while(num_cells--)
{
unsigned alpha;
int x = cell->x;
int area = cell->area;
cover += cell->cover;
++cell;
if(area)
{
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
sl.add_cell(x, alpha);
x++;
}
if(num_cells && cell->x > x)
{
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
if(alpha)
{
sl.add_span(x, cell->x - x, alpha);
}
}
}
if(sl.num_spans() == 0) return false;
sl.finalize(scan_y);
return true;
}
private:
void add_style(int style_id);
//--------------------------------------------------------------------
// Disable copying
rasterizer_compound_aa(const rasterizer_compound_aa<Clip>&);
const rasterizer_compound_aa<Clip>&
operator = (const rasterizer_compound_aa<Clip>&);
private:
rasterizer_cells_aa<cell_style_aa> m_outline;
clip_type m_clipper;
filling_rule_e m_filling_rule;
layer_order_e m_layer_order;
pod_vector<style_info> m_styles; // Active Styles
pod_vector<unsigned> m_ast; // Active Style Table (unique values)
pod_vector<int8u> m_asm; // Active Style Mask
pod_vector<cell_info> m_cells;
pod_vector<cover_type> m_cover_buf;
int m_min_style;
int m_max_style;
coord_type m_start_x;
coord_type m_start_y;
int m_scan_y;
int m_sl_start;
unsigned m_sl_len;
};
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::reset()
{
m_outline.reset();
m_min_style = std::numeric_limits<int>::max();
m_max_style = std::numeric_limits<int>::min();
m_scan_y = std::numeric_limits<int>::max();
m_sl_start = 0;
m_sl_len = 0;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::filling_rule(filling_rule_e filling_rule)
{
m_filling_rule = filling_rule;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::layer_order(layer_order_e order)
{
m_layer_order = order;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1,
double x2, double y2)
{
reset();
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
conv_type::upscale(x2), conv_type::upscale(y2));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::reset_clipping()
{
reset();
m_clipper.reset_clipping();
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::styles(int left, int right)
{
cell_style_aa cell;
cell.initial();
cell.left = (int16)left;
cell.right = (int16)right;
m_outline.style(cell);
if(left >= 0 && left < m_min_style) m_min_style = left;
if(left >= 0 && left > m_max_style) m_max_style = left;
if(right >= 0 && right < m_min_style) m_min_style = right;
if(right >= 0 && right > m_max_style) m_max_style = right;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::move_to(int x, int y)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(m_start_x = conv_type::downscale(x),
m_start_y = conv_type::downscale(y));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::line_to(int x, int y)
{
m_clipper.line_to(m_outline,
conv_type::downscale(x),
conv_type::downscale(y));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::move_to_d(double x, double y)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(m_start_x = conv_type::upscale(x),
m_start_y = conv_type::upscale(y));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::line_to_d(double x, double y)
{
m_clipper.line_to(m_outline,
conv_type::upscale(x),
conv_type::upscale(y));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
move_to_d(x, y);
}
else
if(is_vertex(cmd))
{
line_to_d(x, y);
}
else
if(is_close(cmd))
{
m_clipper.line_to(m_outline, m_start_x, m_start_y);
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::edge(int x1, int y1, int x2, int y2)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
m_clipper.line_to(m_outline,
conv_type::downscale(x2),
conv_type::downscale(y2));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_compound_aa<Clip>::edge_d(double x1, double y1,
double x2, double y2)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
m_clipper.line_to(m_outline,
conv_type::upscale(x2),
conv_type::upscale(y2));
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE void rasterizer_compound_aa<Clip>::sort()
{
m_outline.sort_cells();
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_compound_aa<Clip>::rewind_scanlines()
{
m_outline.sort_cells();
if(m_outline.total_cells() == 0)
{
return false;
}
if(m_max_style < m_min_style)
{
return false;
}
m_scan_y = m_outline.min_y();
m_styles.allocate(m_max_style - m_min_style + 2, 128);
return true;
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE void rasterizer_compound_aa<Clip>::add_style(int style_id)
{
if(style_id < 0) style_id = 0;
else style_id -= m_min_style - 1;
unsigned nbyte = style_id >> 3;
unsigned mask = 1 << (style_id & 7);
style_info* style = &m_styles[style_id];
if((m_asm[nbyte] & mask) == 0)
{
m_ast.add(style_id);
m_asm[nbyte] |= mask;
style->start_cell = 0;
style->num_cells = 0;
style->last_x = std::numeric_limits<int>::min();
}
++style->start_cell;
}
//------------------------------------------------------------------------
// Returns the number of styles
template<class Clip>
unsigned rasterizer_compound_aa<Clip>::sweep_styles()
{
for(;;)
{
if(m_scan_y > m_outline.max_y()) return 0;
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y);
unsigned num_styles = m_max_style - m_min_style + 2;
const cell_style_aa* curr_cell;
unsigned style_id;
style_info* style;
cell_info* cell;
m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles
m_ast.capacity(num_styles, 64);
m_asm.allocate((num_styles + 7) >> 3, 8);
m_asm.zero();
if(num_cells)
{
// Pre-add zero (for no-fill style, that is, -1).
// We need that to ensure that the "-1 style" would go first.
m_asm[0] |= 1;
m_ast.add(0);
style = &m_styles[0];
style->start_cell = 0;
style->num_cells = 0;
style->last_x = std::numeric_limits<int>::min();
m_sl_start = cells[0]->x;
m_sl_len = cells[num_cells-1]->x - m_sl_start + 1;
while(num_cells--)
{
curr_cell = *cells++;
add_style(curr_cell->left);
add_style(curr_cell->right);
}
// Convert the Y-histogram into the array of starting indexes
unsigned i;
unsigned start_cell = 0;
for(i = 0; i < m_ast.size(); i++)
{
style_info& st = m_styles[m_ast[i]];
unsigned v = st.start_cell;
st.start_cell = start_cell;
start_cell += v;
}
cells = m_outline.scanline_cells(m_scan_y);
num_cells = m_outline.scanline_num_cells(m_scan_y);
while(num_cells--)
{
curr_cell = *cells++;
style_id = (curr_cell->left < 0) ? 0 :
curr_cell->left - m_min_style + 1;
style = &m_styles[style_id];
if(curr_cell->x == style->last_x)
{
cell = &m_cells[style->start_cell + style->num_cells - 1];
cell->area += curr_cell->area;
cell->cover += curr_cell->cover;
}
else
{
cell = &m_cells[style->start_cell + style->num_cells];
cell->x = curr_cell->x;
cell->area = curr_cell->area;
cell->cover = curr_cell->cover;
style->last_x = curr_cell->x;
style->num_cells++;
}
style_id = (curr_cell->right < 0) ? 0 :
curr_cell->right - m_min_style + 1;
style = &m_styles[style_id];
if(curr_cell->x == style->last_x)
{
cell = &m_cells[style->start_cell + style->num_cells - 1];
cell->area -= curr_cell->area;
cell->cover -= curr_cell->cover;
}
else
{
cell = &m_cells[style->start_cell + style->num_cells];
cell->x = curr_cell->x;
cell->area = -curr_cell->area;
cell->cover = -curr_cell->cover;
style->last_x = curr_cell->x;
style->num_cells++;
}
}
}
if(m_ast.size() > 1) break;
++m_scan_y;
}
++m_scan_y;
if(m_layer_order != layer_unsorted)
{
range_adaptor<pod_vector<unsigned> > ra(m_ast, 1, m_ast.size() - 1);
if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater);
else quick_sort(ra, unsigned_less);
}
return m_ast.size() - 1;
}
//------------------------------------------------------------------------
// Returns style ID depending of the existing style index
template<class Clip>
AGG_INLINE
unsigned rasterizer_compound_aa<Clip>::style(unsigned style_idx) const
{
return m_ast[style_idx + 1] + m_min_style - 1;
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_compound_aa<Clip>::navigate_scanline(int y)
{
m_outline.sort_cells();
if(m_outline.total_cells() == 0)
{
return false;
}
if(m_max_style < m_min_style)
{
return false;
}
if(y < m_outline.min_y() || y > m_outline.max_y())
{
return false;
}
m_scan_y = y;
m_styles.allocate(m_max_style - m_min_style + 2, 128);
return true;
}
//------------------------------------------------------------------------
template<class Clip>
bool rasterizer_compound_aa<Clip>::hit_test(int tx, int ty)
{
if(!navigate_scanline(ty))
{
return false;
}
unsigned num_styles = sweep_styles();
if(num_styles <= 0)
{
return false;
}
scanline_hit_test sl(tx);
sweep_scanline(sl, -1);
return sl.hit();
}
//------------------------------------------------------------------------
template<class Clip>
cover_type* rasterizer_compound_aa<Clip>::allocate_cover_buffer(unsigned len)
{
m_cover_buf.allocate(len, 256);
return &m_cover_buf[0];
}
}
#endif

View File

@@ -0,0 +1,147 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_OUTLINE_INCLUDED
#define AGG_RASTERIZER_OUTLINE_INCLUDED
#include "agg_basics.h"
namespace agg
{
//======================================================rasterizer_outline
template<class Renderer> class rasterizer_outline
{
public:
explicit rasterizer_outline(Renderer& ren) :
m_ren(&ren),
m_start_x(0),
m_start_y(0),
m_vertices(0)
{}
void attach(Renderer& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
void move_to(int x, int y)
{
m_vertices = 1;
m_ren->move_to(m_start_x = x, m_start_y = y);
}
//--------------------------------------------------------------------
void line_to(int x, int y)
{
++m_vertices;
m_ren->line_to(x, y);
}
//--------------------------------------------------------------------
void move_to_d(double x, double y)
{
move_to(m_ren->coord(x), m_ren->coord(y));
}
//--------------------------------------------------------------------
void line_to_d(double x, double y)
{
line_to(m_ren->coord(x), m_ren->coord(y));
}
//--------------------------------------------------------------------
void close()
{
if(m_vertices > 2)
{
line_to(m_start_x, m_start_y);
}
m_vertices = 0;
}
//--------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
move_to_d(x, y);
}
else
{
if(is_end_poly(cmd))
{
if(is_closed(cmd)) close();
}
else
{
line_to_d(x, y);
}
}
}
//--------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
}
//--------------------------------------------------------------------
template<class VertexSource, class ColorStorage, class PathId>
void render_all_paths(VertexSource& vs,
const ColorStorage& colors,
const PathId& path_id,
unsigned num_paths)
{
for(unsigned i = 0; i < num_paths; i++)
{
m_ren->line_color(colors[i]);
add_path(vs, path_id[i]);
}
}
//--------------------------------------------------------------------
template<class Ctrl> void render_ctrl(Ctrl& c)
{
unsigned i;
for(i = 0; i < c.num_paths(); i++)
{
m_ren->line_color(c.color(i));
add_path(c, i);
}
}
private:
Renderer* m_ren;
int m_start_x;
int m_start_y;
unsigned m_vertices;
};
}
#endif

View File

@@ -0,0 +1,600 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED
#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED
#include <cmath>
#include "agg_basics.h"
#include "agg_line_aa_basics.h"
#include "agg_vertex_sequence.h"
namespace agg
{
//-------------------------------------------------------------------------
inline bool cmp_dist_start(int d) { return d > 0; }
inline bool cmp_dist_end(int d) { return d <= 0; }
//-----------------------------------------------------------line_aa_vertex
// Vertex (x, y) with the distance to the next one. The last vertex has
// the distance between the last and the first points
struct line_aa_vertex
{
int x;
int y;
int len;
line_aa_vertex() {}
line_aa_vertex(int x_, int y_) :
x(x_),
y(y_),
len(0)
{
}
bool operator () (const line_aa_vertex& val)
{
double dx = val.x - x;
double dy = val.y - y;
return (len = uround(std::sqrt(dx * dx + dy * dy))) >
(line_subpixel_scale + line_subpixel_scale / 2);
}
};
//----------------------------------------------------------outline_aa_join_e
enum outline_aa_join_e
{
outline_no_join, //-----outline_no_join
outline_miter_join, //-----outline_miter_join
outline_round_join, //-----outline_round_join
outline_miter_accurate_join //-----outline_accurate_join
};
//=======================================================rasterizer_outline_aa
template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa
{
private:
//------------------------------------------------------------------------
struct draw_vars
{
unsigned idx;
int x1, y1, x2, y2;
line_parameters curr, next;
int lcurr, lnext;
int xb1, yb1, xb2, yb2;
unsigned flags;
};
void draw(draw_vars& dv, unsigned start, unsigned end);
public:
typedef line_aa_vertex vertex_type;
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
explicit rasterizer_outline_aa(Renderer& ren) :
m_ren(&ren),
m_line_join(ren.accurate_join_only() ?
outline_miter_accurate_join :
outline_round_join),
m_round_cap(false),
m_start_x(0),
m_start_y(0)
{}
void attach(Renderer& ren) { m_ren = &ren; }
//------------------------------------------------------------------------
void line_join(outline_aa_join_e join)
{
m_line_join = m_ren->accurate_join_only() ?
outline_miter_accurate_join :
join;
}
bool line_join() const { return m_line_join; }
//------------------------------------------------------------------------
void round_cap(bool v) { m_round_cap = v; }
bool round_cap() const { return m_round_cap; }
//------------------------------------------------------------------------
void move_to(int x, int y)
{
m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y));
}
//------------------------------------------------------------------------
void line_to(int x, int y)
{
m_src_vertices.add(vertex_type(x, y));
}
//------------------------------------------------------------------------
void move_to_d(double x, double y)
{
move_to(Coord::conv(x), Coord::conv(y));
}
//------------------------------------------------------------------------
void line_to_d(double x, double y)
{
line_to(Coord::conv(x), Coord::conv(y));
}
//------------------------------------------------------------------------
void render(bool close_polygon);
//------------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
render(false);
move_to_d(x, y);
}
else
{
if(is_end_poly(cmd))
{
render(is_closed(cmd));
if(is_closed(cmd))
{
move_to(m_start_x, m_start_y);
}
}
else
{
line_to_d(x, y);
}
}
}
//------------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
render(false);
}
//------------------------------------------------------------------------
template<class VertexSource, class ColorStorage, class PathId>
void render_all_paths(VertexSource& vs,
const ColorStorage& colors,
const PathId& path_id,
unsigned num_paths)
{
for(unsigned i = 0; i < num_paths; i++)
{
m_ren->color(colors[i]);
add_path(vs, path_id[i]);
}
}
//------------------------------------------------------------------------
template<class Ctrl> void render_ctrl(Ctrl& c)
{
unsigned i;
for(i = 0; i < c.num_paths(); i++)
{
m_ren->color(c.color(i));
add_path(c, i);
}
}
private:
rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&);
const rasterizer_outline_aa<Renderer, Coord>& operator =
(const rasterizer_outline_aa<Renderer, Coord>&);
Renderer* m_ren;
vertex_storage_type m_src_vertices;
outline_aa_join_e m_line_join;
bool m_round_cap;
int m_start_x;
int m_start_y;
};
//----------------------------------------------------------------------------
template<class Renderer, class Coord>
void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv,
unsigned start,
unsigned end)
{
unsigned i;
const vertex_storage_type::value_type* v;
for(i = start; i < end; i++)
{
if(m_line_join == outline_round_join)
{
dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1);
dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1);
dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1);
dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1);
}
switch(dv.flags)
{
case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break;
case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break;
case 3: m_ren->line0(dv.curr); break;
}
if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
{
m_ren->pie(dv.curr.x2, dv.curr.y2,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x2 + (dv.next.y2 - dv.next.y1),
dv.curr.y2 - (dv.next.x2 - dv.next.x1));
}
dv.x1 = dv.x2;
dv.y1 = dv.y2;
dv.lcurr = dv.lnext;
dv.lnext = m_src_vertices[dv.idx].len;
++dv.idx;
if(dv.idx >= m_src_vertices.size()) dv.idx = 0;
v = &m_src_vertices[dv.idx];
dv.x2 = v->x;
dv.y2 = v->y;
dv.curr = dv.next;
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
dv.xb1 = dv.xb2;
dv.yb1 = dv.yb2;
switch(m_line_join)
{
case outline_no_join:
dv.flags = 3;
break;
case outline_miter_join:
dv.flags >>= 1;
dv.flags |= ((dv.curr.diagonal_quadrant() ==
dv.next.diagonal_quadrant()) << 1);
if((dv.flags & 2) == 0)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
break;
case outline_round_join:
dv.flags >>= 1;
dv.flags |= ((dv.curr.diagonal_quadrant() ==
dv.next.diagonal_quadrant()) << 1);
break;
case outline_miter_accurate_join:
dv.flags = 0;
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
break;
}
}
}
//----------------------------------------------------------------------------
template<class Renderer, class Coord>
void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon)
{
m_src_vertices.close(close_polygon);
draw_vars dv;
const vertex_storage_type::value_type* v;
int x1;
int y1;
int x2;
int y2;
int lprev;
if(close_polygon)
{
if(m_src_vertices.size() >= 3)
{
dv.idx = 2;
v = &m_src_vertices[m_src_vertices.size() - 1];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[0];
x2 = v->x;
y2 = v->y;
dv.lcurr = v->len;
line_parameters prev(x1, y1, x2, y2, lprev);
v = &m_src_vertices[1];
dv.x1 = v->x;
dv.y1 = v->y;
dv.lnext = v->len;
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
v = &m_src_vertices[dv.idx];
dv.x2 = v->x;
dv.y2 = v->y;
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
dv.xb1 = 0;
dv.yb1 = 0;
dv.xb2 = 0;
dv.yb2 = 0;
switch(m_line_join)
{
case outline_no_join:
dv.flags = 3;
break;
case outline_miter_join:
case outline_round_join:
dv.flags =
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
break;
case outline_miter_accurate_join:
dv.flags = 0;
break;
}
if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
}
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 0, m_src_vertices.size());
}
}
else
{
switch(m_src_vertices.size())
{
case 0:
case 1:
break;
case 2:
{
v = &m_src_vertices[0];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[1];
x2 = v->x;
y2 = v->y;
line_parameters lp(x1, y1, x2, y2, lprev);
if(m_round_cap)
{
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
m_ren->line3(lp,
x1 + (y2 - y1),
y1 - (x2 - x1),
x2 + (y2 - y1),
y2 - (x2 - x1));
if(m_round_cap)
{
m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
}
}
break;
case 3:
{
int x3, y3;
int lnext;
v = &m_src_vertices[0];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[1];
x2 = v->x;
y2 = v->y;
lnext = v->len;
v = &m_src_vertices[2];
x3 = v->x;
y3 = v->y;
line_parameters lp1(x1, y1, x2, y2, lprev);
line_parameters lp2(x2, y2, x3, y3, lnext);
if(m_round_cap)
{
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
if(m_line_join == outline_round_join)
{
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
x2 + (y2 - y1), y2 - (x2 - x1));
m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
x2 + (y3 - y2), y2 - (x3 - x2));
m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
x3 + (y3 - y2), y3 - (x3 - x2));
}
else
{
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
dv.xb1, dv.yb1);
m_ren->line3(lp2, dv.xb1, dv.yb1,
x3 + (y3 - y2), y3 - (x3 - x2));
}
if(m_round_cap)
{
m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
}
}
break;
default:
{
dv.idx = 3;
v = &m_src_vertices[0];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[1];
x2 = v->x;
y2 = v->y;
dv.lcurr = v->len;
line_parameters prev(x1, y1, x2, y2, lprev);
v = &m_src_vertices[2];
dv.x1 = v->x;
dv.y1 = v->y;
dv.lnext = v->len;
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
v = &m_src_vertices[dv.idx];
dv.x2 = v->x;
dv.y2 = v->y;
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
dv.xb1 = 0;
dv.yb1 = 0;
dv.xb2 = 0;
dv.yb2 = 0;
switch(m_line_join)
{
case outline_no_join:
dv.flags = 3;
break;
case outline_miter_join:
case outline_round_join:
dv.flags =
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
break;
case outline_miter_accurate_join:
dv.flags = 0;
break;
}
if(m_round_cap)
{
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
if((dv.flags & 1) == 0)
{
if(m_line_join == outline_round_join)
{
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
x2 + (y2 - y1), y2 - (x2 - x1));
m_ren->pie(prev.x2, prev.y2,
x2 + (y2 - y1), y2 - (x2 - x1),
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
}
else
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
dv.xb1, dv.yb1);
}
}
else
{
m_ren->line1(prev,
x1 + (y2 - y1),
y1 - (x2 - x1));
}
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 1, m_src_vertices.size() - 2);
if((dv.flags & 1) == 0)
{
if(m_line_join == outline_round_join)
{
m_ren->line3(dv.curr,
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
else
{
m_ren->line3(dv.curr, dv.xb1, dv.yb1,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
}
else
{
m_ren->line2(dv.curr,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
if(m_round_cap)
{
m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
}
break;
}
}
m_src_vertices.remove_all();
}
}
#endif

View File

@@ -0,0 +1,481 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
//
// The author gratefully acknowleges the support of David Turner,
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
// libray - in producing this work. See http://www.freetype.org for details.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com
//
// Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers.
//
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED
#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED
#include "agg_rasterizer_cells_aa.h"
#include "agg_rasterizer_sl_clip.h"
#include "agg_rasterizer_scanline_aa_nogamma.h"
#include "agg_gamma_functions.h"
namespace agg
{
//==================================================rasterizer_scanline_aa
// Polygon rasterizer that is used to render filled polygons with
// high-quality Anti-Aliasing. Internally, by default, the class uses
// integer coordinates in format 24.8, i.e. 24 bits for integer part
// and 8 bits for fractional - see poly_subpixel_shift. This class can be
// used in the following way:
//
// 1. filling_rule(filling_rule_e ft) - optional.
//
// 2. gamma() - optional.
//
// 3. reset()
//
// 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
// more than one contour, but each contour must consist of at least 3
// vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
// is the absolute minimum of vertices that define a triangle.
// The algorithm does not check either the number of vertices nor
// coincidence of their coordinates, but in the worst case it just
// won't draw anything.
// The orger of the vertices (clockwise or counterclockwise)
// is important when using the non-zero filling rule (fill_non_zero).
// In this case the vertex order of all the contours must be the same
// if you want your intersecting polygons to be without "holes".
// You actually can use different vertices order. If the contours do not
// intersect each other the order is not important anyway. If they do,
// contours with the same vertex order will be rendered without "holes"
// while the intersecting contours with different orders will have "holes".
//
// filling_rule() and gamma() can be called anytime before "sweeping".
//------------------------------------------------------------------------
template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa
{
enum status
{
status_initial,
status_move_to,
status_line_to,
status_closed
};
public:
typedef Clip clip_type;
typedef typename Clip::conv_type conv_type;
typedef typename Clip::coord_type coord_type;
enum aa_scale_e
{
aa_shift = 8,
aa_scale = 1 << aa_shift,
aa_mask = aa_scale - 1,
aa_scale2 = aa_scale * 2,
aa_mask2 = aa_scale2 - 1
};
//--------------------------------------------------------------------
rasterizer_scanline_aa(unsigned cell_block_limit=1024) :
m_outline(cell_block_limit),
m_clipper(),
m_filling_rule(fill_non_zero),
m_auto_close(true),
m_start_x(0),
m_start_y(0),
m_status(status_initial)
{
int i;
for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
}
//--------------------------------------------------------------------
template<class GammaF>
rasterizer_scanline_aa(const GammaF& gamma_function, unsigned cell_block_limit) :
m_outline(cell_block_limit),
m_clipper(m_outline),
m_filling_rule(fill_non_zero),
m_auto_close(true),
m_start_x(0),
m_start_y(0),
m_status(status_initial)
{
gamma(gamma_function);
}
//--------------------------------------------------------------------
void reset();
void reset_clipping();
void clip_box(double x1, double y1, double x2, double y2);
void filling_rule(filling_rule_e filling_rule);
void auto_close(bool flag) { m_auto_close = flag; }
//--------------------------------------------------------------------
template<class GammaF> void gamma(const GammaF& gamma_function)
{
int i;
for(i = 0; i < aa_scale; i++)
{
m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
}
}
//--------------------------------------------------------------------
unsigned apply_gamma(unsigned cover) const
{
return m_gamma[cover];
}
//--------------------------------------------------------------------
void move_to(int x, int y);
void line_to(int x, int y);
void move_to_d(double x, double y);
void line_to_d(double x, double y);
void close_polygon();
void add_vertex(double x, double y, unsigned cmd);
void edge(int x1, int y1, int x2, int y2);
void edge_d(double x1, double y1, double x2, double y2);
//-------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
if(m_outline.sorted()) reset();
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
}
//--------------------------------------------------------------------
int min_x() const { return m_outline.min_x(); }
int min_y() const { return m_outline.min_y(); }
int max_x() const { return m_outline.max_x(); }
int max_y() const { return m_outline.max_y(); }
//--------------------------------------------------------------------
void sort();
bool rewind_scanlines();
bool navigate_scanline(int y);
//--------------------------------------------------------------------
AGG_INLINE unsigned calculate_alpha(int area) const
{
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
if(cover < 0) cover = -cover;
if(m_filling_rule == fill_even_odd)
{
cover &= aa_mask2;
if(cover > aa_scale)
{
cover = aa_scale2 - cover;
}
}
if(cover > aa_mask) cover = aa_mask;
return m_gamma[cover];
}
//--------------------------------------------------------------------
template<class Scanline> bool sweep_scanline(Scanline& sl)
{
for(;;)
{
if(m_scan_y > m_outline.max_y()) return false;
sl.reset_spans();
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
int cover = 0;
while(num_cells)
{
const cell_aa* cur_cell = *cells;
int x = cur_cell->x;
int area = cur_cell->area;
unsigned alpha;
cover += cur_cell->cover;
//accumulate all cells with the same X
while(--num_cells)
{
cur_cell = *++cells;
if(cur_cell->x != x) break;
area += cur_cell->area;
cover += cur_cell->cover;
}
if(area)
{
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
if(alpha)
{
sl.add_cell(x, alpha);
}
x++;
}
if(num_cells && cur_cell->x > x)
{
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
if(alpha)
{
sl.add_span(x, cur_cell->x - x, alpha);
}
}
}
if(sl.num_spans()) break;
++m_scan_y;
}
sl.finalize(m_scan_y);
++m_scan_y;
return true;
}
//--------------------------------------------------------------------
bool hit_test(int tx, int ty);
private:
//--------------------------------------------------------------------
// Disable copying
rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&);
const rasterizer_scanline_aa<Clip>&
operator = (const rasterizer_scanline_aa<Clip>&);
private:
rasterizer_cells_aa<cell_aa> m_outline;
clip_type m_clipper;
int m_gamma[aa_scale];
filling_rule_e m_filling_rule;
bool m_auto_close;
coord_type m_start_x;
coord_type m_start_y;
unsigned m_status;
int m_scan_y;
};
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::reset()
{
m_outline.reset();
m_status = status_initial;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule)
{
m_filling_rule = filling_rule;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1,
double x2, double y2)
{
reset();
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
conv_type::upscale(x2), conv_type::upscale(y2));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::reset_clipping()
{
reset();
m_clipper.reset_clipping();
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::close_polygon()
{
if(m_status == status_line_to)
{
m_clipper.line_to(m_outline, m_start_x, m_start_y);
m_status = status_closed;
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
{
if(m_outline.sorted()) reset();
if(m_auto_close) close_polygon();
m_clipper.move_to(m_start_x = conv_type::downscale(x),
m_start_y = conv_type::downscale(y));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::line_to(int x, int y)
{
m_clipper.line_to(m_outline,
conv_type::downscale(x),
conv_type::downscale(y));
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
{
if(m_outline.sorted()) reset();
if(m_auto_close) close_polygon();
m_clipper.move_to(m_start_x = conv_type::upscale(x),
m_start_y = conv_type::upscale(y));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y)
{
m_clipper.line_to(m_outline,
conv_type::upscale(x),
conv_type::upscale(y));
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
move_to_d(x, y);
}
else
if(is_vertex(cmd))
{
line_to_d(x, y);
}
else
if(is_close(cmd))
{
close_polygon();
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
m_clipper.line_to(m_outline,
conv_type::downscale(x2),
conv_type::downscale(y2));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1,
double x2, double y2)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
m_clipper.line_to(m_outline,
conv_type::upscale(x2),
conv_type::upscale(y2));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::sort()
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
if(m_outline.total_cells() == 0)
{
return false;
}
m_scan_y = m_outline.min_y();
return true;
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
if(m_outline.total_cells() == 0 ||
y < m_outline.min_y() ||
y > m_outline.max_y())
{
return false;
}
m_scan_y = y;
return true;
}
//------------------------------------------------------------------------
template<class Clip>
bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)
{
if(!navigate_scanline(ty)) return false;
scanline_hit_test sl(tx);
sweep_scanline(sl);
return sl.hit();
}
}
#endif

View File

@@ -0,0 +1,483 @@
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
//
// The author gratefully acknowleges the support of David Turner,
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
// libray - in producing this work. See http://www.freetype.org for details.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com
//
// Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers.
//
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_SCANLINE_AA_NOGAMMA_INCLUDED
#define AGG_RASTERIZER_SCANLINE_AA_NOGAMMA_INCLUDED
#include <limits>
#include "agg_rasterizer_cells_aa.h"
#include "agg_rasterizer_sl_clip.h"
namespace agg
{
//-----------------------------------------------------------------cell_aa
// A pixel cell. There're no constructors defined and it was done
// intentionally in order to avoid extra overhead when allocating an
// array of cells.
struct cell_aa
{
int x;
int y;
int cover;
int area;
void initial()
{
x = std::numeric_limits<int>::max();
y = std::numeric_limits<int>::max();
cover = 0;
area = 0;
}
void style(const cell_aa&) {}
int not_equal(int ex, int ey, const cell_aa&) const
{
return ((unsigned)ex - (unsigned)x) | ((unsigned)ey - (unsigned)y);
}
};
//==================================================rasterizer_scanline_aa_nogamma
// Polygon rasterizer that is used to render filled polygons with
// high-quality Anti-Aliasing. Internally, by default, the class uses
// integer coordinates in format 24.8, i.e. 24 bits for integer part
// and 8 bits for fractional - see poly_subpixel_shift. This class can be
// used in the following way:
//
// 1. filling_rule(filling_rule_e ft) - optional.
//
// 2. gamma() - optional.
//
// 3. reset()
//
// 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
// more than one contour, but each contour must consist of at least 3
// vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
// is the absolute minimum of vertices that define a triangle.
// The algorithm does not check either the number of vertices nor
// coincidence of their coordinates, but in the worst case it just
// won't draw anything.
// The orger of the vertices (clockwise or counterclockwise)
// is important when using the non-zero filling rule (fill_non_zero).
// In this case the vertex order of all the contours must be the same
// if you want your intersecting polygons to be without "holes".
// You actually can use different vertices order. If the contours do not
// intersect each other the order is not important anyway. If they do,
// contours with the same vertex order will be rendered without "holes"
// while the intersecting contours with different orders will have "holes".
//
// filling_rule() and gamma() can be called anytime before "sweeping".
//------------------------------------------------------------------------
template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa_nogamma
{
enum status
{
status_initial,
status_move_to,
status_line_to,
status_closed
};
public:
typedef Clip clip_type;
typedef typename Clip::conv_type conv_type;
typedef typename Clip::coord_type coord_type;
enum aa_scale_e
{
aa_shift = 8,
aa_scale = 1 << aa_shift,
aa_mask = aa_scale - 1,
aa_scale2 = aa_scale * 2,
aa_mask2 = aa_scale2 - 1
};
//--------------------------------------------------------------------
rasterizer_scanline_aa_nogamma(unsigned cell_block_limit=1024) :
m_outline(cell_block_limit),
m_clipper(),
m_filling_rule(fill_non_zero),
m_auto_close(true),
m_start_x(0),
m_start_y(0),
m_status(status_initial)
{
}
//--------------------------------------------------------------------
void reset();
void reset_clipping();
void clip_box(double x1, double y1, double x2, double y2);
void filling_rule(filling_rule_e filling_rule);
void auto_close(bool flag) { m_auto_close = flag; }
//--------------------------------------------------------------------
unsigned apply_gamma(unsigned cover) const
{
return cover;
}
//--------------------------------------------------------------------
void move_to(int x, int y);
void line_to(int x, int y);
void move_to_d(double x, double y);
void line_to_d(double x, double y);
void close_polygon();
void add_vertex(double x, double y, unsigned cmd);
void edge(int x1, int y1, int x2, int y2);
void edge_d(double x1, double y1, double x2, double y2);
//-------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
if(m_outline.sorted()) reset();
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
}
//--------------------------------------------------------------------
int min_x() const { return m_outline.min_x(); }
int min_y() const { return m_outline.min_y(); }
int max_x() const { return m_outline.max_x(); }
int max_y() const { return m_outline.max_y(); }
//--------------------------------------------------------------------
void sort();
bool rewind_scanlines();
bool navigate_scanline(int y);
//--------------------------------------------------------------------
AGG_INLINE unsigned calculate_alpha(int area) const
{
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
if(cover < 0) cover = -cover;
if(m_filling_rule == fill_even_odd)
{
cover &= aa_mask2;
if(cover > aa_scale)
{
cover = aa_scale2 - cover;
}
}
if(cover > aa_mask) cover = aa_mask;
return cover;
}
//--------------------------------------------------------------------
template<class Scanline> bool sweep_scanline(Scanline& sl)
{
for(;;)
{
if(m_scan_y > m_outline.max_y()) return false;
sl.reset_spans();
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
int cover = 0;
while(num_cells)
{
const cell_aa* cur_cell = *cells;
int x = cur_cell->x;
int area = cur_cell->area;
unsigned alpha;
cover += cur_cell->cover;
//accumulate all cells with the same X
while(--num_cells)
{
cur_cell = *++cells;
if(cur_cell->x != x) break;
area += cur_cell->area;
cover += cur_cell->cover;
}
if(area)
{
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
if(alpha)
{
sl.add_cell(x, alpha);
}
x++;
}
if(num_cells && cur_cell->x > x)
{
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
if(alpha)
{
sl.add_span(x, cur_cell->x - x, alpha);
}
}
}
if(sl.num_spans()) break;
++m_scan_y;
}
sl.finalize(m_scan_y);
++m_scan_y;
return true;
}
//--------------------------------------------------------------------
bool hit_test(int tx, int ty);
private:
//--------------------------------------------------------------------
// Disable copying
rasterizer_scanline_aa_nogamma(const rasterizer_scanline_aa_nogamma<Clip>&);
const rasterizer_scanline_aa_nogamma<Clip>&
operator = (const rasterizer_scanline_aa_nogamma<Clip>&);
private:
rasterizer_cells_aa<cell_aa> m_outline;
clip_type m_clipper;
filling_rule_e m_filling_rule;
bool m_auto_close;
coord_type m_start_x;
coord_type m_start_y;
unsigned m_status;
int m_scan_y;
};
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::reset()
{
m_outline.reset();
m_status = status_initial;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::filling_rule(filling_rule_e filling_rule)
{
m_filling_rule = filling_rule;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::clip_box(double x1, double y1,
double x2, double y2)
{
reset();
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
conv_type::upscale(x2), conv_type::upscale(y2));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::reset_clipping()
{
reset();
m_clipper.reset_clipping();
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::close_polygon()
{
if(m_status == status_line_to)
{
m_clipper.line_to(m_outline, m_start_x, m_start_y);
m_status = status_closed;
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::move_to(int x, int y)
{
if(m_outline.sorted()) reset();
if(m_auto_close) close_polygon();
m_clipper.move_to(m_start_x = conv_type::downscale(x),
m_start_y = conv_type::downscale(y));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::line_to(int x, int y)
{
m_clipper.line_to(m_outline,
conv_type::downscale(x),
conv_type::downscale(y));
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::move_to_d(double x, double y)
{
if(m_outline.sorted()) reset();
if(m_auto_close) close_polygon();
m_clipper.move_to(m_start_x = conv_type::upscale(x),
m_start_y = conv_type::upscale(y));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::line_to_d(double x, double y)
{
m_clipper.line_to(m_outline,
conv_type::upscale(x),
conv_type::upscale(y));
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
move_to_d(x, y);
}
else
if(is_vertex(cmd))
{
line_to_d(x, y);
}
else
if(is_close(cmd))
{
close_polygon();
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::edge(int x1, int y1, int x2, int y2)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
m_clipper.line_to(m_outline,
conv_type::downscale(x2),
conv_type::downscale(y2));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::edge_d(double x1, double y1,
double x2, double y2)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
m_clipper.line_to(m_outline,
conv_type::upscale(x2),
conv_type::upscale(y2));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa_nogamma<Clip>::sort()
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa_nogamma<Clip>::rewind_scanlines()
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
if(m_outline.total_cells() == 0)
{
return false;
}
m_scan_y = m_outline.min_y();
return true;
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa_nogamma<Clip>::navigate_scanline(int y)
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
if(m_outline.total_cells() == 0 ||
y < m_outline.min_y() ||
y > m_outline.max_y())
{
return false;
}
m_scan_y = y;
return true;
}
//------------------------------------------------------------------------
template<class Clip>
bool rasterizer_scanline_aa_nogamma<Clip>::hit_test(int tx, int ty)
{
if(!navigate_scanline(ty)) return false;
scanline_hit_test sl(tx);
sweep_scanline(sl);
return sl.hit();
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More