Index: trunk/INSTALL
===================================================================
--- trunk/INSTALL (nonexistent)
+++ trunk/INSTALL (revision 1)
@@ -0,0 +1,21 @@
+Standard procedure for camv-rnd beta testing.
+
+1. install librnd from pcb-rnd
+
+ svn checkout svn://repo.hu/pcb-rnd/trunk
+ ./configure
+ make
+ make install
+
+ While configuring, make sure to include the gtk2 HID as builtin
+ (plugins won't yet work with camv-rnd).
+
+2. copy Makefile.conf.in to Makefile.conf and edit it
+
+3. make
+
+4. at the moment there is no make install; the only way to run the test
+ version is from work/camv-rnd:
+
+ ./camv-rnd filename1 filename2 ...
+
Index: trunk/Makefile.conf.in
===================================================================
--- trunk/Makefile.conf.in (nonexistent)
+++ trunk/Makefile.conf.in (revision 1)
@@ -0,0 +1,2 @@
+# installation prefix of pcb-rnd's librnd
+LIBRND_ROOT=/usr
Index: trunk/TODO
===================================================================
--- trunk/TODO (nonexistent)
+++ trunk/TODO (revision 1)
@@ -0,0 +1,5 @@
+- tedax:
+ - redesign poly support because of number of points
+- hidlib:
+ - make plugin dir configurable
+ - separate hidlib plugin dir from hidlib app plugin dirs
Index: trunk/doc/gerb_poly_clr/README
===================================================================
--- trunk/doc/gerb_poly_clr/README (nonexistent)
+++ trunk/doc/gerb_poly_clr/README (revision 1)
@@ -0,0 +1,5 @@
+how different EDA tools export a polygon with holes:
+
+easyeda: draws LPC polygons (filled circle approximations)
+kicad5: cut-in slicer with a trace superposed on top of all poly edges
+
Index: trunk/doc/gerb_poly_clr/easyeda.gbr
===================================================================
--- trunk/doc/gerb_poly_clr/easyeda.gbr (nonexistent)
+++ trunk/doc/gerb_poly_clr/easyeda.gbr (revision 1)
@@ -0,0 +1,773 @@
+G04 Layer: TopLayer*
+G04 EasyEDA v6.1.49, Sat, 08 Jun 2019 15:20:32 GMT*
+G04 67eb3f2711d84385b02b45c74739b1d2,f2e733f61c4c4f0caaaab363faf1c69b,NaN*
+G04 Gerber Generator version 0.2*
+G04 Scale: 100 percent, Rotated: No, Reflected: No *
+G04 Dimensions in millimeters *
+G04 leading zeros omitted , absolute positions ,3 integer and 3 decimal *
+%FSLAX33Y33*%
+%MOMM*%
+G90*
+G71D02*
+
+%ADD11C,0.609600*%
+
+%LPD*%
+G36*
+G01X19633Y19734D02*
+G01X366Y19734D01*
+G01X352Y19733D01*
+G01X338Y19730D01*
+G01X324Y19725D01*
+G01X311Y19718D01*
+G01X300Y19709D01*
+G01X290Y19699D01*
+G01X281Y19688D01*
+G01X274Y19675D01*
+G01X269Y19661D01*
+G01X266Y19647D01*
+G01X265Y19633D01*
+G01X265Y366D01*
+G01X266Y352D01*
+G01X269Y338D01*
+G01X274Y324D01*
+G01X281Y311D01*
+G01X290Y300D01*
+G01X300Y290D01*
+G01X311Y281D01*
+G01X324Y274D01*
+G01X338Y269D01*
+G01X352Y266D01*
+G01X366Y265D01*
+G01X19633Y265D01*
+G01X19647Y266D01*
+G01X19661Y269D01*
+G01X19675Y274D01*
+G01X19688Y281D01*
+G01X19699Y290D01*
+G01X19709Y300D01*
+G01X19718Y311D01*
+G01X19725Y324D01*
+G01X19730Y338D01*
+G01X19733Y352D01*
+G01X19734Y366D01*
+G01X19734Y19633D01*
+G01X19733Y19647D01*
+G01X19730Y19661D01*
+G01X19725Y19675D01*
+G01X19718Y19688D01*
+G01X19709Y19699D01*
+G01X19699Y19709D01*
+G01X19688Y19718D01*
+G01X19675Y19725D01*
+G01X19661Y19730D01*
+G01X19647Y19733D01*
+G01X19633Y19734D01*
+G37*
+
+%LPC*%
+G36*
+G01X17813Y2456D02*
+G01X17780Y2457D01*
+G01X17746Y2456D01*
+G01X17712Y2453D01*
+G01X17679Y2448D01*
+G01X17646Y2441D01*
+G01X17614Y2432D01*
+G01X17582Y2421D01*
+G01X17551Y2408D01*
+G01X17520Y2393D01*
+G01X17491Y2376D01*
+G01X17463Y2358D01*
+G01X17436Y2338D01*
+G01X17410Y2317D01*
+G01X17385Y2294D01*
+G01X17362Y2269D01*
+G01X17341Y2243D01*
+G01X17321Y2216D01*
+G01X17303Y2188D01*
+G01X17286Y2159D01*
+G01X17271Y2128D01*
+G01X17258Y2097D01*
+G01X17247Y2065D01*
+G01X17238Y2033D01*
+G01X17231Y2000D01*
+G01X17226Y1967D01*
+G01X17223Y1933D01*
+G01X17222Y1899D01*
+G01X17223Y1866D01*
+G01X17226Y1832D01*
+G01X17231Y1799D01*
+G01X17238Y1766D01*
+G01X17247Y1734D01*
+G01X17258Y1702D01*
+G01X17271Y1671D01*
+G01X17286Y1640D01*
+G01X17303Y1611D01*
+G01X17321Y1583D01*
+G01X17341Y1556D01*
+G01X17362Y1530D01*
+G01X17385Y1505D01*
+G01X17410Y1482D01*
+G01X17436Y1461D01*
+G01X17463Y1441D01*
+G01X17491Y1423D01*
+G01X17520Y1406D01*
+G01X17551Y1391D01*
+G01X17582Y1378D01*
+G01X17614Y1367D01*
+G01X17646Y1358D01*
+G01X17679Y1351D01*
+G01X17712Y1346D01*
+G01X17746Y1343D01*
+G01X17780Y1342D01*
+G01X17813Y1343D01*
+G01X17847Y1346D01*
+G01X17880Y1351D01*
+G01X17913Y1358D01*
+G01X17945Y1367D01*
+G01X17977Y1378D01*
+G01X18008Y1391D01*
+G01X18039Y1406D01*
+G01X18068Y1423D01*
+G01X18096Y1441D01*
+G01X18123Y1461D01*
+G01X18149Y1482D01*
+G01X18174Y1505D01*
+G01X18197Y1530D01*
+G01X18218Y1556D01*
+G01X18238Y1583D01*
+G01X18256Y1611D01*
+G01X18273Y1640D01*
+G01X18288Y1671D01*
+G01X18301Y1702D01*
+G01X18312Y1734D01*
+G01X18321Y1766D01*
+G01X18328Y1799D01*
+G01X18333Y1832D01*
+G01X18336Y1866D01*
+G01X18337Y1899D01*
+G01X18336Y1933D01*
+G01X18333Y1967D01*
+G01X18328Y2000D01*
+G01X18321Y2033D01*
+G01X18312Y2065D01*
+G01X18301Y2097D01*
+G01X18288Y2128D01*
+G01X18273Y2159D01*
+G01X18256Y2188D01*
+G01X18238Y2216D01*
+G01X18218Y2243D01*
+G01X18197Y2269D01*
+G01X18174Y2294D01*
+G01X18149Y2317D01*
+G01X18123Y2338D01*
+G01X18096Y2358D01*
+G01X18068Y2376D01*
+G01X18039Y2393D01*
+G01X18008Y2408D01*
+G01X17977Y2421D01*
+G01X17945Y2432D01*
+G01X17913Y2441D01*
+G01X17880Y2448D01*
+G01X17847Y2453D01*
+G01X17813Y2456D01*
+G37*
+G36*
+G01X10193Y10076D02*
+G01X10160Y10077D01*
+G01X10126Y10076D01*
+G01X10092Y10073D01*
+G01X10059Y10068D01*
+G01X10026Y10061D01*
+G01X9994Y10052D01*
+G01X9962Y10041D01*
+G01X9931Y10028D01*
+G01X9900Y10013D01*
+G01X9871Y9996D01*
+G01X9843Y9978D01*
+G01X9816Y9958D01*
+G01X9790Y9937D01*
+G01X9765Y9914D01*
+G01X9742Y9889D01*
+G01X9721Y9863D01*
+G01X9701Y9836D01*
+G01X9683Y9808D01*
+G01X9666Y9779D01*
+G01X9651Y9748D01*
+G01X9638Y9717D01*
+G01X9627Y9685D01*
+G01X9618Y9653D01*
+G01X9611Y9620D01*
+G01X9606Y9587D01*
+G01X9603Y9553D01*
+G01X9602Y9519D01*
+G01X9603Y9486D01*
+G01X9606Y9452D01*
+G01X9611Y9419D01*
+G01X9618Y9386D01*
+G01X9627Y9354D01*
+G01X9638Y9322D01*
+G01X9651Y9291D01*
+G01X9666Y9260D01*
+G01X9683Y9231D01*
+G01X9701Y9203D01*
+G01X9721Y9176D01*
+G01X9742Y9150D01*
+G01X9765Y9125D01*
+G01X9790Y9102D01*
+G01X9816Y9081D01*
+G01X9843Y9061D01*
+G01X9871Y9043D01*
+G01X9900Y9026D01*
+G01X9931Y9011D01*
+G01X9962Y8998D01*
+G01X9994Y8987D01*
+G01X10026Y8978D01*
+G01X10059Y8971D01*
+G01X10092Y8966D01*
+G01X10126Y8963D01*
+G01X10160Y8962D01*
+G01X10193Y8963D01*
+G01X10227Y8966D01*
+G01X10260Y8971D01*
+G01X10293Y8978D01*
+G01X10325Y8987D01*
+G01X10357Y8998D01*
+G01X10388Y9011D01*
+G01X10419Y9026D01*
+G01X10448Y9043D01*
+G01X10476Y9061D01*
+G01X10503Y9081D01*
+G01X10529Y9102D01*
+G01X10554Y9125D01*
+G01X10577Y9150D01*
+G01X10598Y9176D01*
+G01X10618Y9203D01*
+G01X10636Y9231D01*
+G01X10653Y9260D01*
+G01X10668Y9291D01*
+G01X10681Y9322D01*
+G01X10692Y9354D01*
+G01X10701Y9386D01*
+G01X10708Y9419D01*
+G01X10713Y9452D01*
+G01X10716Y9486D01*
+G01X10717Y9519D01*
+G01X10716Y9553D01*
+G01X10713Y9587D01*
+G01X10708Y9620D01*
+G01X10701Y9653D01*
+G01X10692Y9685D01*
+G01X10681Y9717D01*
+G01X10668Y9748D01*
+G01X10653Y9779D01*
+G01X10636Y9808D01*
+G01X10618Y9836D01*
+G01X10598Y9863D01*
+G01X10577Y9889D01*
+G01X10554Y9914D01*
+G01X10529Y9937D01*
+G01X10503Y9958D01*
+G01X10476Y9978D01*
+G01X10448Y9996D01*
+G01X10419Y10013D01*
+G01X10388Y10028D01*
+G01X10357Y10041D01*
+G01X10325Y10052D01*
+G01X10293Y10061D01*
+G01X10260Y10068D01*
+G01X10227Y10073D01*
+G01X10193Y10076D01*
+G37*
+G36*
+G01X2573Y17696D02*
+G01X2540Y17697D01*
+G01X2506Y17696D01*
+G01X2472Y17693D01*
+G01X2439Y17688D01*
+G01X2406Y17681D01*
+G01X2374Y17672D01*
+G01X2342Y17661D01*
+G01X2311Y17648D01*
+G01X2280Y17633D01*
+G01X2251Y17616D01*
+G01X2223Y17598D01*
+G01X2196Y17578D01*
+G01X2170Y17557D01*
+G01X2145Y17534D01*
+G01X2122Y17509D01*
+G01X2101Y17483D01*
+G01X2081Y17456D01*
+G01X2063Y17428D01*
+G01X2046Y17399D01*
+G01X2031Y17368D01*
+G01X2018Y17337D01*
+G01X2007Y17305D01*
+G01X1998Y17273D01*
+G01X1991Y17240D01*
+G01X1986Y17207D01*
+G01X1983Y17173D01*
+G01X1982Y17139D01*
+G01X1983Y17106D01*
+G01X1986Y17072D01*
+G01X1991Y17039D01*
+G01X1998Y17006D01*
+G01X2007Y16974D01*
+G01X2018Y16942D01*
+G01X2031Y16911D01*
+G01X2046Y16880D01*
+G01X2063Y16851D01*
+G01X2081Y16823D01*
+G01X2101Y16796D01*
+G01X2122Y16770D01*
+G01X2145Y16745D01*
+G01X2170Y16722D01*
+G01X2196Y16701D01*
+G01X2223Y16681D01*
+G01X2251Y16663D01*
+G01X2280Y16646D01*
+G01X2311Y16631D01*
+G01X2342Y16618D01*
+G01X2374Y16607D01*
+G01X2406Y16598D01*
+G01X2439Y16591D01*
+G01X2472Y16586D01*
+G01X2506Y16583D01*
+G01X2540Y16582D01*
+G01X2573Y16583D01*
+G01X2607Y16586D01*
+G01X2640Y16591D01*
+G01X2673Y16598D01*
+G01X2705Y16607D01*
+G01X2737Y16618D01*
+G01X2768Y16631D01*
+G01X2799Y16646D01*
+G01X2828Y16663D01*
+G01X2856Y16681D01*
+G01X2883Y16701D01*
+G01X2909Y16722D01*
+G01X2934Y16745D01*
+G01X2957Y16770D01*
+G01X2978Y16796D01*
+G01X2998Y16823D01*
+G01X3016Y16851D01*
+G01X3033Y16880D01*
+G01X3048Y16911D01*
+G01X3061Y16942D01*
+G01X3072Y16974D01*
+G01X3081Y17006D01*
+G01X3088Y17039D01*
+G01X3093Y17072D01*
+G01X3096Y17106D01*
+G01X3097Y17139D01*
+G01X3096Y17173D01*
+G01X3093Y17207D01*
+G01X3088Y17240D01*
+G01X3081Y17273D01*
+G01X3072Y17305D01*
+G01X3061Y17337D01*
+G01X3048Y17368D01*
+G01X3033Y17399D01*
+G01X3016Y17428D01*
+G01X2998Y17456D01*
+G01X2978Y17483D01*
+G01X2957Y17509D01*
+G01X2934Y17534D01*
+G01X2909Y17557D01*
+G01X2883Y17578D01*
+G01X2856Y17598D01*
+G01X2828Y17616D01*
+G01X2799Y17633D01*
+G01X2768Y17648D01*
+G01X2737Y17661D01*
+G01X2705Y17672D01*
+G01X2673Y17681D01*
+G01X2640Y17688D01*
+G01X2607Y17693D01*
+G01X2573Y17696D01*
+G37*
+
+%LPD*%
+G36*
+G01X19633Y19734D02*
+G01X366Y19734D01*
+G01X352Y19733D01*
+G01X338Y19730D01*
+G01X324Y19725D01*
+G01X311Y19718D01*
+G01X300Y19709D01*
+G01X290Y19699D01*
+G01X281Y19688D01*
+G01X274Y19675D01*
+G01X269Y19661D01*
+G01X266Y19647D01*
+G01X265Y19633D01*
+G01X265Y366D01*
+G01X266Y352D01*
+G01X269Y338D01*
+G01X274Y324D01*
+G01X281Y311D01*
+G01X290Y300D01*
+G01X300Y290D01*
+G01X311Y281D01*
+G01X324Y274D01*
+G01X338Y269D01*
+G01X352Y266D01*
+G01X366Y265D01*
+G01X19633Y265D01*
+G01X19647Y266D01*
+G01X19661Y269D01*
+G01X19675Y274D01*
+G01X19688Y281D01*
+G01X19699Y290D01*
+G01X19709Y300D01*
+G01X19718Y311D01*
+G01X19725Y324D01*
+G01X19730Y338D01*
+G01X19733Y352D01*
+G01X19734Y366D01*
+G01X19734Y19633D01*
+G01X19733Y19647D01*
+G01X19730Y19661D01*
+G01X19725Y19675D01*
+G01X19718Y19688D01*
+G01X19709Y19699D01*
+G01X19699Y19709D01*
+G01X19688Y19718D01*
+G01X19675Y19725D01*
+G01X19661Y19730D01*
+G01X19647Y19733D01*
+G01X19633Y19734D01*
+G37*
+
+%LPC*%
+G36*
+G01X17813Y2456D02*
+G01X17780Y2457D01*
+G01X17746Y2456D01*
+G01X17712Y2453D01*
+G01X17679Y2448D01*
+G01X17646Y2441D01*
+G01X17614Y2432D01*
+G01X17582Y2421D01*
+G01X17551Y2408D01*
+G01X17520Y2393D01*
+G01X17491Y2376D01*
+G01X17463Y2358D01*
+G01X17436Y2338D01*
+G01X17410Y2317D01*
+G01X17385Y2294D01*
+G01X17362Y2269D01*
+G01X17341Y2243D01*
+G01X17321Y2216D01*
+G01X17303Y2188D01*
+G01X17286Y2159D01*
+G01X17271Y2128D01*
+G01X17258Y2097D01*
+G01X17247Y2065D01*
+G01X17238Y2033D01*
+G01X17231Y2000D01*
+G01X17226Y1967D01*
+G01X17223Y1933D01*
+G01X17222Y1899D01*
+G01X17223Y1866D01*
+G01X17226Y1832D01*
+G01X17231Y1799D01*
+G01X17238Y1766D01*
+G01X17247Y1734D01*
+G01X17258Y1702D01*
+G01X17271Y1671D01*
+G01X17286Y1640D01*
+G01X17303Y1611D01*
+G01X17321Y1583D01*
+G01X17341Y1556D01*
+G01X17362Y1530D01*
+G01X17385Y1505D01*
+G01X17410Y1482D01*
+G01X17436Y1461D01*
+G01X17463Y1441D01*
+G01X17491Y1423D01*
+G01X17520Y1406D01*
+G01X17551Y1391D01*
+G01X17582Y1378D01*
+G01X17614Y1367D01*
+G01X17646Y1358D01*
+G01X17679Y1351D01*
+G01X17712Y1346D01*
+G01X17746Y1343D01*
+G01X17780Y1342D01*
+G01X17813Y1343D01*
+G01X17847Y1346D01*
+G01X17880Y1351D01*
+G01X17913Y1358D01*
+G01X17945Y1367D01*
+G01X17977Y1378D01*
+G01X18008Y1391D01*
+G01X18039Y1406D01*
+G01X18068Y1423D01*
+G01X18096Y1441D01*
+G01X18123Y1461D01*
+G01X18149Y1482D01*
+G01X18174Y1505D01*
+G01X18197Y1530D01*
+G01X18218Y1556D01*
+G01X18238Y1583D01*
+G01X18256Y1611D01*
+G01X18273Y1640D01*
+G01X18288Y1671D01*
+G01X18301Y1702D01*
+G01X18312Y1734D01*
+G01X18321Y1766D01*
+G01X18328Y1799D01*
+G01X18333Y1832D01*
+G01X18336Y1866D01*
+G01X18337Y1899D01*
+G01X18336Y1933D01*
+G01X18333Y1967D01*
+G01X18328Y2000D01*
+G01X18321Y2033D01*
+G01X18312Y2065D01*
+G01X18301Y2097D01*
+G01X18288Y2128D01*
+G01X18273Y2159D01*
+G01X18256Y2188D01*
+G01X18238Y2216D01*
+G01X18218Y2243D01*
+G01X18197Y2269D01*
+G01X18174Y2294D01*
+G01X18149Y2317D01*
+G01X18123Y2338D01*
+G01X18096Y2358D01*
+G01X18068Y2376D01*
+G01X18039Y2393D01*
+G01X18008Y2408D01*
+G01X17977Y2421D01*
+G01X17945Y2432D01*
+G01X17913Y2441D01*
+G01X17880Y2448D01*
+G01X17847Y2453D01*
+G01X17813Y2456D01*
+G37*
+G36*
+G01X10193Y10076D02*
+G01X10160Y10077D01*
+G01X10126Y10076D01*
+G01X10092Y10073D01*
+G01X10059Y10068D01*
+G01X10026Y10061D01*
+G01X9994Y10052D01*
+G01X9962Y10041D01*
+G01X9931Y10028D01*
+G01X9900Y10013D01*
+G01X9871Y9996D01*
+G01X9843Y9978D01*
+G01X9816Y9958D01*
+G01X9790Y9937D01*
+G01X9765Y9914D01*
+G01X9742Y9889D01*
+G01X9721Y9863D01*
+G01X9701Y9836D01*
+G01X9683Y9808D01*
+G01X9666Y9779D01*
+G01X9651Y9748D01*
+G01X9638Y9717D01*
+G01X9627Y9685D01*
+G01X9618Y9653D01*
+G01X9611Y9620D01*
+G01X9606Y9587D01*
+G01X9603Y9553D01*
+G01X9602Y9519D01*
+G01X9603Y9486D01*
+G01X9606Y9452D01*
+G01X9611Y9419D01*
+G01X9618Y9386D01*
+G01X9627Y9354D01*
+G01X9638Y9322D01*
+G01X9651Y9291D01*
+G01X9666Y9260D01*
+G01X9683Y9231D01*
+G01X9701Y9203D01*
+G01X9721Y9176D01*
+G01X9742Y9150D01*
+G01X9765Y9125D01*
+G01X9790Y9102D01*
+G01X9816Y9081D01*
+G01X9843Y9061D01*
+G01X9871Y9043D01*
+G01X9900Y9026D01*
+G01X9931Y9011D01*
+G01X9962Y8998D01*
+G01X9994Y8987D01*
+G01X10026Y8978D01*
+G01X10059Y8971D01*
+G01X10092Y8966D01*
+G01X10126Y8963D01*
+G01X10160Y8962D01*
+G01X10193Y8963D01*
+G01X10227Y8966D01*
+G01X10260Y8971D01*
+G01X10293Y8978D01*
+G01X10325Y8987D01*
+G01X10357Y8998D01*
+G01X10388Y9011D01*
+G01X10419Y9026D01*
+G01X10448Y9043D01*
+G01X10476Y9061D01*
+G01X10503Y9081D01*
+G01X10529Y9102D01*
+G01X10554Y9125D01*
+G01X10577Y9150D01*
+G01X10598Y9176D01*
+G01X10618Y9203D01*
+G01X10636Y9231D01*
+G01X10653Y9260D01*
+G01X10668Y9291D01*
+G01X10681Y9322D01*
+G01X10692Y9354D01*
+G01X10701Y9386D01*
+G01X10708Y9419D01*
+G01X10713Y9452D01*
+G01X10716Y9486D01*
+G01X10717Y9519D01*
+G01X10716Y9553D01*
+G01X10713Y9587D01*
+G01X10708Y9620D01*
+G01X10701Y9653D01*
+G01X10692Y9685D01*
+G01X10681Y9717D01*
+G01X10668Y9748D01*
+G01X10653Y9779D01*
+G01X10636Y9808D01*
+G01X10618Y9836D01*
+G01X10598Y9863D01*
+G01X10577Y9889D01*
+G01X10554Y9914D01*
+G01X10529Y9937D01*
+G01X10503Y9958D01*
+G01X10476Y9978D01*
+G01X10448Y9996D01*
+G01X10419Y10013D01*
+G01X10388Y10028D01*
+G01X10357Y10041D01*
+G01X10325Y10052D01*
+G01X10293Y10061D01*
+G01X10260Y10068D01*
+G01X10227Y10073D01*
+G01X10193Y10076D01*
+G37*
+G36*
+G01X2573Y17696D02*
+G01X2540Y17697D01*
+G01X2506Y17696D01*
+G01X2472Y17693D01*
+G01X2439Y17688D01*
+G01X2406Y17681D01*
+G01X2374Y17672D01*
+G01X2342Y17661D01*
+G01X2311Y17648D01*
+G01X2280Y17633D01*
+G01X2251Y17616D01*
+G01X2223Y17598D01*
+G01X2196Y17578D01*
+G01X2170Y17557D01*
+G01X2145Y17534D01*
+G01X2122Y17509D01*
+G01X2101Y17483D01*
+G01X2081Y17456D01*
+G01X2063Y17428D01*
+G01X2046Y17399D01*
+G01X2031Y17368D01*
+G01X2018Y17337D01*
+G01X2007Y17305D01*
+G01X1998Y17273D01*
+G01X1991Y17240D01*
+G01X1986Y17207D01*
+G01X1983Y17173D01*
+G01X1982Y17139D01*
+G01X1983Y17106D01*
+G01X1986Y17072D01*
+G01X1991Y17039D01*
+G01X1998Y17006D01*
+G01X2007Y16974D01*
+G01X2018Y16942D01*
+G01X2031Y16911D01*
+G01X2046Y16880D01*
+G01X2063Y16851D01*
+G01X2081Y16823D01*
+G01X2101Y16796D01*
+G01X2122Y16770D01*
+G01X2145Y16745D01*
+G01X2170Y16722D01*
+G01X2196Y16701D01*
+G01X2223Y16681D01*
+G01X2251Y16663D01*
+G01X2280Y16646D01*
+G01X2311Y16631D01*
+G01X2342Y16618D01*
+G01X2374Y16607D01*
+G01X2406Y16598D01*
+G01X2439Y16591D01*
+G01X2472Y16586D01*
+G01X2506Y16583D01*
+G01X2540Y16582D01*
+G01X2573Y16583D01*
+G01X2607Y16586D01*
+G01X2640Y16591D01*
+G01X2673Y16598D01*
+G01X2705Y16607D01*
+G01X2737Y16618D01*
+G01X2768Y16631D01*
+G01X2799Y16646D01*
+G01X2828Y16663D01*
+G01X2856Y16681D01*
+G01X2883Y16701D01*
+G01X2909Y16722D01*
+G01X2934Y16745D01*
+G01X2957Y16770D01*
+G01X2978Y16796D01*
+G01X2998Y16823D01*
+G01X3016Y16851D01*
+G01X3033Y16880D01*
+G01X3048Y16911D01*
+G01X3061Y16942D01*
+G01X3072Y16974D01*
+G01X3081Y17006D01*
+G01X3088Y17039D01*
+G01X3093Y17072D01*
+G01X3096Y17106D01*
+G01X3097Y17139D01*
+G01X3096Y17173D01*
+G01X3093Y17207D01*
+G01X3088Y17240D01*
+G01X3081Y17273D01*
+G01X3072Y17305D01*
+G01X3061Y17337D01*
+G01X3048Y17368D01*
+G01X3033Y17399D01*
+G01X3016Y17428D01*
+G01X2998Y17456D01*
+G01X2978Y17483D01*
+G01X2957Y17509D01*
+G01X2934Y17534D01*
+G01X2909Y17557D01*
+G01X2883Y17578D01*
+G01X2856Y17598D01*
+G01X2828Y17616D01*
+G01X2799Y17633D01*
+G01X2768Y17648D01*
+G01X2737Y17661D01*
+G01X2705Y17672D01*
+G01X2673Y17681D01*
+G01X2640Y17688D01*
+G01X2607Y17693D01*
+G01X2573Y17696D01*
+G37*
+
+%LPD*%
+G54D11*
+G01X2540Y17139D03*
+G01X17780Y1899D03*
+G01X10160Y9519D03*
+M00*
+M02*
Index: trunk/doc/gerb_poly_clr/kicad5.1.2.gbr
===================================================================
--- trunk/doc/gerb_poly_clr/kicad5.1.2.gbr (nonexistent)
+++ trunk/doc/gerb_poly_clr/kicad5.1.2.gbr (revision 1)
@@ -0,0 +1,245 @@
+G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.2*
+G04 #@! TF.CreationDate,2019-06-10T10:04:51+01:00*
+G04 #@! TF.ProjectId,camv,63616d76-2e6b-4696-9361-645f70636258,rev?*
+G04 #@! TF.SameCoordinates,Original*
+G04 #@! TF.FileFunction,Copper,L1,Top*
+G04 #@! TF.FilePolarity,Positive*
+%FSLAX46Y46*%
+G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
+G04 Created by KiCad (PCBNEW 5.1.2) date 2019-06-10 10:04:51*
+%MOMM*%
+%LPD*%
+G04 APERTURE LIST*
+%ADD10C,0.800000*%
+%ADD11C,0.254000*%
+G04 APERTURE END LIST*
+D10*
+X127000000Y-81900000D03*
+X133300000Y-87900000D03*
+X139200000Y-94000000D03*
+D11*
+G36*
+X142873000Y-97873000D02*
+G01*
+X123127000Y-97873000D01*
+X123127000Y-93898061D01*
+X138165000Y-93898061D01*
+X138165000Y-94101939D01*
+X138204774Y-94301898D01*
+X138282795Y-94490256D01*
+X138396063Y-94659774D01*
+X138540226Y-94803937D01*
+X138709744Y-94917205D01*
+X138898102Y-94995226D01*
+X139098061Y-95035000D01*
+X139301939Y-95035000D01*
+X139501898Y-94995226D01*
+X139690256Y-94917205D01*
+X139859774Y-94803937D01*
+X140003937Y-94659774D01*
+X140117205Y-94490256D01*
+X140195226Y-94301898D01*
+X140235000Y-94101939D01*
+X140235000Y-93898061D01*
+X140195226Y-93698102D01*
+X140117205Y-93509744D01*
+X140003937Y-93340226D01*
+X139859774Y-93196063D01*
+X139690256Y-93082795D01*
+X139501898Y-93004774D01*
+X139301939Y-92965000D01*
+X139098061Y-92965000D01*
+X138898102Y-93004774D01*
+X138709744Y-93082795D01*
+X138540226Y-93196063D01*
+X138396063Y-93340226D01*
+X138282795Y-93509744D01*
+X138204774Y-93698102D01*
+X138165000Y-93898061D01*
+X123127000Y-93898061D01*
+X123127000Y-87798061D01*
+X132265000Y-87798061D01*
+X132265000Y-88001939D01*
+X132304774Y-88201898D01*
+X132382795Y-88390256D01*
+X132496063Y-88559774D01*
+X132640226Y-88703937D01*
+X132809744Y-88817205D01*
+X132998102Y-88895226D01*
+X133198061Y-88935000D01*
+X133401939Y-88935000D01*
+X133601898Y-88895226D01*
+X133790256Y-88817205D01*
+X133959774Y-88703937D01*
+X134103937Y-88559774D01*
+X134217205Y-88390256D01*
+X134295226Y-88201898D01*
+X134335000Y-88001939D01*
+X134335000Y-87798061D01*
+X134295226Y-87598102D01*
+X134217205Y-87409744D01*
+X134103937Y-87240226D01*
+X133959774Y-87096063D01*
+X133790256Y-86982795D01*
+X133601898Y-86904774D01*
+X133401939Y-86865000D01*
+X133198061Y-86865000D01*
+X132998102Y-86904774D01*
+X132809744Y-86982795D01*
+X132640226Y-87096063D01*
+X132496063Y-87240226D01*
+X132382795Y-87409744D01*
+X132304774Y-87598102D01*
+X132265000Y-87798061D01*
+X123127000Y-87798061D01*
+X123127000Y-81798061D01*
+X125965000Y-81798061D01*
+X125965000Y-82001939D01*
+X126004774Y-82201898D01*
+X126082795Y-82390256D01*
+X126196063Y-82559774D01*
+X126340226Y-82703937D01*
+X126509744Y-82817205D01*
+X126698102Y-82895226D01*
+X126898061Y-82935000D01*
+X127101939Y-82935000D01*
+X127301898Y-82895226D01*
+X127490256Y-82817205D01*
+X127659774Y-82703937D01*
+X127803937Y-82559774D01*
+X127917205Y-82390256D01*
+X127995226Y-82201898D01*
+X128035000Y-82001939D01*
+X128035000Y-81798061D01*
+X127995226Y-81598102D01*
+X127917205Y-81409744D01*
+X127803937Y-81240226D01*
+X127659774Y-81096063D01*
+X127490256Y-80982795D01*
+X127301898Y-80904774D01*
+X127101939Y-80865000D01*
+X126898061Y-80865000D01*
+X126698102Y-80904774D01*
+X126509744Y-80982795D01*
+X126340226Y-81096063D01*
+X126196063Y-81240226D01*
+X126082795Y-81409744D01*
+X126004774Y-81598102D01*
+X125965000Y-81798061D01*
+X123127000Y-81798061D01*
+X123127000Y-78127000D01*
+X142873000Y-78127000D01*
+X142873000Y-97873000D01*
+X142873000Y-97873000D01*
+G37*
+X142873000Y-97873000D02*
+X123127000Y-97873000D01*
+X123127000Y-93898061D01*
+X138165000Y-93898061D01*
+X138165000Y-94101939D01*
+X138204774Y-94301898D01*
+X138282795Y-94490256D01*
+X138396063Y-94659774D01*
+X138540226Y-94803937D01*
+X138709744Y-94917205D01*
+X138898102Y-94995226D01*
+X139098061Y-95035000D01*
+X139301939Y-95035000D01*
+X139501898Y-94995226D01*
+X139690256Y-94917205D01*
+X139859774Y-94803937D01*
+X140003937Y-94659774D01*
+X140117205Y-94490256D01*
+X140195226Y-94301898D01*
+X140235000Y-94101939D01*
+X140235000Y-93898061D01*
+X140195226Y-93698102D01*
+X140117205Y-93509744D01*
+X140003937Y-93340226D01*
+X139859774Y-93196063D01*
+X139690256Y-93082795D01*
+X139501898Y-93004774D01*
+X139301939Y-92965000D01*
+X139098061Y-92965000D01*
+X138898102Y-93004774D01*
+X138709744Y-93082795D01*
+X138540226Y-93196063D01*
+X138396063Y-93340226D01*
+X138282795Y-93509744D01*
+X138204774Y-93698102D01*
+X138165000Y-93898061D01*
+X123127000Y-93898061D01*
+X123127000Y-87798061D01*
+X132265000Y-87798061D01*
+X132265000Y-88001939D01*
+X132304774Y-88201898D01*
+X132382795Y-88390256D01*
+X132496063Y-88559774D01*
+X132640226Y-88703937D01*
+X132809744Y-88817205D01*
+X132998102Y-88895226D01*
+X133198061Y-88935000D01*
+X133401939Y-88935000D01*
+X133601898Y-88895226D01*
+X133790256Y-88817205D01*
+X133959774Y-88703937D01*
+X134103937Y-88559774D01*
+X134217205Y-88390256D01*
+X134295226Y-88201898D01*
+X134335000Y-88001939D01*
+X134335000Y-87798061D01*
+X134295226Y-87598102D01*
+X134217205Y-87409744D01*
+X134103937Y-87240226D01*
+X133959774Y-87096063D01*
+X133790256Y-86982795D01*
+X133601898Y-86904774D01*
+X133401939Y-86865000D01*
+X133198061Y-86865000D01*
+X132998102Y-86904774D01*
+X132809744Y-86982795D01*
+X132640226Y-87096063D01*
+X132496063Y-87240226D01*
+X132382795Y-87409744D01*
+X132304774Y-87598102D01*
+X132265000Y-87798061D01*
+X123127000Y-87798061D01*
+X123127000Y-81798061D01*
+X125965000Y-81798061D01*
+X125965000Y-82001939D01*
+X126004774Y-82201898D01*
+X126082795Y-82390256D01*
+X126196063Y-82559774D01*
+X126340226Y-82703937D01*
+X126509744Y-82817205D01*
+X126698102Y-82895226D01*
+X126898061Y-82935000D01*
+X127101939Y-82935000D01*
+X127301898Y-82895226D01*
+X127490256Y-82817205D01*
+X127659774Y-82703937D01*
+X127803937Y-82559774D01*
+X127917205Y-82390256D01*
+X127995226Y-82201898D01*
+X128035000Y-82001939D01*
+X128035000Y-81798061D01*
+X127995226Y-81598102D01*
+X127917205Y-81409744D01*
+X127803937Y-81240226D01*
+X127659774Y-81096063D01*
+X127490256Y-80982795D01*
+X127301898Y-80904774D01*
+X127101939Y-80865000D01*
+X126898061Y-80865000D01*
+X126698102Y-80904774D01*
+X126509744Y-80982795D01*
+X126340226Y-81096063D01*
+X126196063Y-81240226D01*
+X126082795Y-81409744D01*
+X126004774Y-81598102D01*
+X125965000Y-81798061D01*
+X123127000Y-81798061D01*
+X123127000Y-78127000D01*
+X142873000Y-78127000D01*
+X142873000Y-97873000D01*
+M02*
Index: trunk/doc/tedax-camv.html
===================================================================
--- trunk/doc/tedax-camv.html (nonexistent)
+++ trunk/doc/tedax-camv.html (revision 1)
@@ -0,0 +1,133 @@
+
+
+
+ tEDAx - camv layer
+
+
+
+ tEDAx - camv layer
+
+ purpose
+
+Provides a minimalistic language for describing layers for camv-rnd. The
+motivation behind this format is to:
+
+ ease development and testing of camv-rnd
+ allow the user to make annotations on the GUI that can be saved and loaded
+ allow 3rd party tools to generate such annotations in a simple format
+
+
+ data model
+
+Each layer block describes a single layer. The structure of data
+described here are closely related to the internal representation
+camv-rnd has. The layer is drawn using positive (draw)
+and negative (clear) polarity objects. Order of drawing between two
+polarity lines are random, but drawing order of polarity blocks is
+preserved.
+
+Each group block describes a single group of objects with a name unique
+within the file. Layers can reference a group by name to place it on the layer.
+Group references can not make any transformation to the group - the
+purpose of the feature is not supporting footprints or macros, but to group
+objects together. The grouping affects selection and object highlight.
+
+The coordinate system is a two dimensional cartesian system with 0;0 being
+the bottom left corner. Angle 0 is y=0;x>0 and positive delta angles are
+CCW.
+
+
blocks
+
+Layer block type is "camv_layer", version is "v1". The unique identifier
+is the user visible name of the layer (a single file may normally contain
+multiple layers). A layer block contains layer properties and drawing
+primitives.
+
+Group block type is "camv_grp", version is "v1". The unique identifier is
+used for referencing the group from layers. A group block contains drawing
+primitives (other than grp) and may contain the unit line from layer properties.
+The group block must precede any reference to the group. Group polarity is
+always inherited from the layer that is drawing the group, the group can not
+change polarity.
+
+
+
Layer properties
+
+
+ command parameter names explanation
+
+ color #rrggbb
+ Specify preferred/default layer color. camv-rnd will use this
+ color for the layer after load. Six hexadecimal digits prefixed
+ with a hashmark (#). If color is present, it must precede the
+ any polarity line within the layer block. There can be at most
+ one color line in a layer block.
+
+ unit u
+ Switch units to u , which is m, mm, inch or mil. Any new layer
+ or group starts with unit mm. The unit line can be used multiple
+ times within a layer description: the effect of the line lasts
+ until a new unit line is written or until the end of the layer or
+ group block.
+
+ polarity p
+ Switch polarity to p , which is either draw or clear .
+ Any new layer starts with polarity draw . The polarity
+ line can be used multiple times within a layer description: the
+ effect of the line lasts until a new polarity line is written or
+ until the end of the layer block.
+
+
+ Drawing primitives
+
+
+ command parameter names explanation
+
+ arc cx cy r th start delta
+ Draw an arc using a circular pen of diameter th . Coordinates
+ cx and cy are the center of the arc that has a
+ (centerline) radius of r . Arguments start and delta
+ determine the angle span.
+
+ line x1 y1 x2 y2 th
+ Draw an arc using a circular pen of diameter th , from x1;y1
+ to x2;y2 (centerline coordinates).
+
+ poly x1 y1 x2 y2 ... xN yN
+ Draw a filled polygon with a zero diameter pen, using coordinate
+ pairs addressing vertices (corners) of the polygon. Each vertex is
+ listed only once (the last vertex does not need to match the first).
+ The polygon can not intersect itself, may not contain holes and has
+ to have at least 3 vertices.
+
+ grp n
+ Place the group named n defined in a group block.
+
+
+ Example
+
+
+tEDAx v1
+
+begin camv_grp v1 arrow1
+ line 10 10 15 10 1
+ line 15 10 13 8 1
+ line 15 10 13 12 1
+end camv_grp
+
+begin camv_layer v1 pcb\ design\ errors
+ color #ff0000
+ arc 14 11 3 0.5 -20 150
+ poly 20 20 21 21 22 25
+ unit mil
+ grp arrow1
+ line 350 350 550 550 30
+ polarity clear
+ line 350 340 550 560 5
+end camv_layer
+
+
+
+Note: despite the "unit mil" line in the layer, arrow1 is created using
+mm unit because the group has its own unit context that is set to mm when
+the group is parsed.
Index: trunk/src/Makefile
===================================================================
--- trunk/src/Makefile (nonexistent)
+++ trunk/src/Makefile (revision 1)
@@ -0,0 +1,42 @@
+include ../Makefile.conf
+include $(LIBRND_ROOT)/share/librnd/librnd.mak
+
+CFLAGS = -Wall -g -I. $(CFLAGS_HIDLIB)
+LDFLAGS = $(LDFLAGS_HIDLIB)
+
+CORE_OBJS = camv-rnd.o data.o obj_any.o obj_arc.o obj_line.o obj_poly.o obj_grp.o gui_act.o draw.o crosshair.o rtree.o plug_io.o plug_io_act.o conf_core.o
+TEDAX_OBJS = tedax/parse.o tedax/io_tedax.o
+GUI_OBJS = gui/layersel.o gui/camv_gui.o
+GERBD_OBJS = gerb/gedraw.o gerb/geparse.o gerb/gexpr.o gerb/gex.tab.o
+GERB_OBJS = $(GERBD_OBJS) gerb/gerb2camv.o
+EXC_OBJS = excellon/excellon.o
+
+
+RNDLIB = $(LIBRND_ROOT)/lib/librnd-hid.a $(LIBRND_ROOT)/lib/librnd-poly.a $(LIBRND_ROOT)/lib/librnd-3rd.a
+
+OBJS = $(CORE_OBJS) $(GUI_OBJS) $(GERB_OBJS) $(TEDAX_OBJS) $(EXC_OBJS)
+
+all: camv-rnd gerb/gedump
+
+include Makefile.dep
+
+camv-rnd: $(OBJS) $(RNDLIB)
+ $(CC) -o camv-rnd $^ $(LDFLAGS)
+
+gerb/gedump: $(GERBD_OBJS) gerb/gedump.o $(RNDLIB)
+ $(CC) -o gerb/gedump $^ $(LDFLAGS)
+
+gerbyacc: gerb/gex.y gerb/gex.h
+ cd gerb && byacc -b gex -d -p gex -P gex.y
+
+conf_core_fields.h: conf_core.h
+ AWK=awk $(TRUNK)/scconfig/gen_conf.sh < conf_core.h > conf_core_fields.h
+
+clean:
+ rm -f $(OBJS) $(GERBD_OBJS) gerb/gedump.o
+
+dep:
+ ./depgen
+ make -f Makefile.depgen
+
+FORCE:
Index: trunk/src/Makefile.dep
===================================================================
--- trunk/src/Makefile.dep (nonexistent)
+++ trunk/src/Makefile.dep (revision 1)
@@ -0,0 +1,589 @@
+### Generated file, do not edit, run make dep ###
+
+camv-rnd.o: camv-rnd.c ../../trunk/src_3rd/puplug/libs.h \
+ ../../trunk/src_3rd/puplug/puplug.h ../../trunk/src_3rd/puplug/os_dep.h \
+ ../../trunk/src_3rd/puplug/config.h ../../trunk/src_3rd/puplug/libs.h \
+ ../../trunk/src/unit.h ../../trunk/config.h ../../trunk/src/hid_init.h \
+ ../../trunk/src_3rd/genvector/vtp0.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h ../../trunk/src/hid.h \
+ ../../trunk/src/conf.h ../../trunk/src/pcb-printf.h \
+ ../../trunk/src_3rd/liblihata/lihata.h ../../trunk/src/list_conf.h \
+ ../../trunk/src/conf.h ../../trunk/src/buildin.hidlib.h \
+ ../../trunk/src/compat_misc.h ../../trunk/src/plugins.h \
+ ../../trunk/src_3rd/puplug/error.h gui_act.h data.h \
+ ../../trunk/src/global_typedefs.h camv_typedefs.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/color.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h plug_io.h conf_core.h
+conf_core.o: conf_core.c ../../trunk/config.h conf_core.h \
+ ../../trunk/src/conf.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/unit.h \
+ ../../trunk/src/pcb-printf.h ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src_3rd/genvector/vtp0.h \
+ ../../trunk/src/list_conf.h ../../trunk/src/conf.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h ../../trunk/src/color.h \
+ conf_core_fields.h
+crosshair.o: crosshair.c ../../trunk/src/event.h ../../trunk/config.h \
+ ../../trunk/src/unit.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/hidlib.h \
+ ../../trunk/src/crosshair.h ../../trunk/src/vtonpoint.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h ../../trunk/src/route.h \
+ ../../trunk/src/hidlib_conf.h ../../trunk/src/conf.h \
+ ../../trunk/src/pcb-printf.h ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/genvector/vtp0.h ../../trunk/src/list_conf.h \
+ ../../trunk/src/grid.h ../../trunk/src/board.h \
+ ../../trunk/src/vtroutestyle.h ../../trunk/src/layer_grp.h \
+ ../../trunk/src/rats_patch.h data.h ../../trunk/src/global_typedefs.h \
+ camv_typedefs.h ../../trunk/src/hidlib.h ../../trunk/src/color.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h
+data.o: data.c ../../trunk/config.h ../../trunk/src/event.h \
+ ../../trunk/src/unit.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/hidlib.h data.h \
+ ../../trunk/src/global_typedefs.h camv_typedefs.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src_3rd/genvector/vtp0.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h obj_any.h obj_common.h \
+ ../../trunk/src/hid.h ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h obj_arc.h obj_line.h obj_poly.h \
+ ../../trunk/src/vtc0.h obj_grp.h ../../trunk/src/box.h conf_core.h \
+ ../../trunk/src/conf.h ../../trunk/src/pcb-printf.h \
+ ../../trunk/src_3rd/liblihata/lihata.h ../../trunk/src/list_conf.h \
+ ../../trunk/src/conf.h
+draw.o: draw.c ../../trunk/src/hid.h ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/config.h \
+ ../../trunk/src/error.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/unit.h \
+ ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h obj_any.h camv_typedefs.h \
+ data.h ../../trunk/src/global_typedefs.h ../../trunk/src/hidlib.h \
+ ../../trunk/src/color.h ../../trunk/src_3rd/genvector/vtp0.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h obj_common.h obj_arc.h \
+ obj_line.h obj_poly.h ../../trunk/src/vtc0.h obj_grp.h
+gui_act.o: gui_act.c ../../trunk/src/actions.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/config.h \
+ ../../trunk/src/error.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/unit.h \
+ ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/libfungw/fungw.h ../../trunk/src_3rd/genht/htpp.h \
+ ../../trunk/src/compat_misc.h data.h ../../trunk/src/global_typedefs.h \
+ camv_typedefs.h ../../trunk/src/hidlib.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/vtp0.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h ../../trunk/src/dolists.h
+obj_any.o: obj_any.c ../../trunk/config.h obj_any.h camv_typedefs.h \
+ data.h ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h ../../trunk/src/hidlib.h ../../trunk/src/color.h \
+ ../../trunk/src/global_typedefs.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src_3rd/genvector/vtp0.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h obj_common.h \
+ ../../trunk/src/hid.h ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h obj_arc.h obj_line.h obj_poly.h \
+ ../../trunk/src/vtc0.h obj_grp.h
+obj_arc.o: obj_arc.c ../../trunk/config.h obj_arc.h obj_common.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h camv_typedefs.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/attrib.h \
+ ../../trunk/src/layer.h ../../trunk/src/globalconst.h \
+ ../../trunk/src/color.h ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h obj_any.h data.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/vtp0.h obj_line.h obj_poly.h \
+ ../../trunk/src/vtc0.h obj_grp.h ../../trunk/src/hid_inlines.h \
+ ../../trunk/src/hid.h
+obj_grp.o: obj_grp.c ../../trunk/config.h obj_grp.h obj_common.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h camv_typedefs.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/attrib.h \
+ ../../trunk/src/layer.h ../../trunk/src/globalconst.h \
+ ../../trunk/src/color.h ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h obj_any.h data.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/vtp0.h obj_arc.h obj_line.h obj_poly.h \
+ ../../trunk/src/vtc0.h
+obj_line.o: obj_line.c ../../trunk/config.h obj_line.h obj_common.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h camv_typedefs.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/attrib.h \
+ ../../trunk/src/layer.h ../../trunk/src/globalconst.h \
+ ../../trunk/src/color.h ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h obj_any.h data.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/vtp0.h obj_arc.h obj_poly.h \
+ ../../trunk/src/vtc0.h obj_grp.h ../../trunk/src/hid_inlines.h \
+ ../../trunk/src/hid.h
+obj_poly.o: obj_poly.c ../../trunk/config.h obj_poly.h obj_common.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h camv_typedefs.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/attrib.h \
+ ../../trunk/src/layer.h ../../trunk/src/globalconst.h \
+ ../../trunk/src/color.h ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h ../../trunk/src/vtc0.h \
+ obj_any.h data.h ../../trunk/src/hidlib.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/vtp0.h obj_arc.h obj_line.h obj_grp.h
+plug_io.o: plug_io.c ../../trunk/config.h \
+ ../../trunk/src_3rd/genvector/vtp0.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h ../../trunk/src/safe_fs.h ../../trunk/src/conf.h \
+ ../../trunk/src/pcb-printf.h ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/list_conf.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h plug_io.h data.h \
+ ../../trunk/src/global_typedefs.h camv_typedefs.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/color.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h
+plug_io_act.o: plug_io_act.c ../../trunk/config.h \
+ ../../trunk/src/actions.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/libfungw/fungw.h ../../trunk/src_3rd/genht/htpp.h \
+ ../../trunk/src/compat_misc.h ../../trunk/src/event.h \
+ ../../trunk/src/hidlib.h data.h ../../trunk/src/global_typedefs.h \
+ camv_typedefs.h ../../trunk/src/hidlib.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/vtp0.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h plug_io.h plug_io_act.h \
+ ../../trunk/src/dolists.h
+rtree.o: rtree.c ../../trunk/config.h rtree.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h ../../trunk/src_3rd/genrtree/genrtree_api.h \
+ ../../trunk/src_3rd/genrtree/genrtree_impl.h \
+ ../../trunk/src_3rd/genrtree/genrtree_search.h \
+ ../../trunk/src_3rd/genrtree/genrtree_delete.h \
+ ../../trunk/src_3rd/genrtree/genrtree_debug.h
+excellon.o: excellon/excellon.c ../../trunk/config.h \
+ ../../trunk/src/error.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/unit.h \
+ ../../trunk/src/safe_fs.h ../../trunk/src/conf.h \
+ ../../trunk/src/pcb-printf.h ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src_3rd/genvector/vtp0.h \
+ ../../trunk/src/list_conf.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h ../../trunk/src/compat_misc.h \
+ ../../trunk/src/math_helper.h data.h ../../trunk/src/global_typedefs.h \
+ camv_typedefs.h ../../trunk/src/hidlib.h ../../trunk/src/color.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h plug_io.h data.h obj_any.h \
+ obj_common.h ../../trunk/src/hid.h ../../trunk/src/error.h \
+ ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h obj_arc.h \
+ obj_line.h obj_poly.h ../../trunk/src/vtc0.h obj_grp.h
+gedraw.o: gerb/gedraw.c ../../trunk/config.h gerb/gedraw.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src_3rd/genht/ht.h \
+ ../../trunk/src_3rd/genht/hash.h ../../trunk/src_3rd/genvector/vtp0.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h ../../trunk/src/vtc0.h gerb/gexpr.h \
+ ../../trunk/src_3rd/genvector/vtd0.h gerb/gex.tab.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.c gerb/geparse.h \
+ ../../trunk/src_3rd/genht/htsp.h
+gedump.o: gerb/gedump.c gerb/geparse.h gerb/gedraw.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src_3rd/genht/ht.h \
+ ../../trunk/src_3rd/genht/hash.h ../../trunk/src_3rd/genvector/vtp0.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/config.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/unit.h ../../trunk/src/vtc0.h \
+ gerb/gexpr.h ../../trunk/src_3rd/genvector/vtd0.h gerb/gex.tab.h \
+ ../../trunk/src_3rd/genht/htsp.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h
+geparse.o: gerb/geparse.c ../../trunk/config.h \
+ ../../trunk/src_3rd/genht/hash.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h gerb/geparse.h \
+ gerb/gedraw.h ../../trunk/src_3rd/genht/htip.h \
+ ../../trunk/src_3rd/genvector/vtp0.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/unit.h ../../trunk/src/vtc0.h \
+ gerb/gexpr.h ../../trunk/src_3rd/genvector/vtd0.h gerb/gex.tab.h \
+ ../../trunk/src/error.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/compat_misc.h
+gerb2camv.o: gerb/gerb2camv.c ../../trunk/config.h \
+ ../../trunk/src/error.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/unit.h \
+ ../../trunk/src/safe_fs.h ../../trunk/src/conf.h \
+ ../../trunk/src/pcb-printf.h ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src_3rd/genvector/vtp0.h \
+ ../../trunk/src/list_conf.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h ../../trunk/src/compat_misc.h \
+ ../../trunk/src/rotate.h ../../trunk/src/compat_misc.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/polygon1_gen.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/polyarea.h data.h \
+ ../../trunk/src/global_typedefs.h camv_typedefs.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/color.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h plug_io.h data.h obj_any.h \
+ obj_common.h ../../trunk/src/hid.h ../../trunk/src/error.h \
+ ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/obj_text_list.h ../../trunk/src/obj_text.h \
+ ../../trunk/src/font.h ../../trunk/src_3rd/genht/htip.h \
+ ../../trunk/src/box.h ../../trunk/src/math_helper.h \
+ ../../trunk/src/misc_util.h obj_arc.h obj_line.h obj_poly.h \
+ ../../trunk/src/vtc0.h obj_grp.h gerb/geparse.h gerb/gedraw.h \
+ ../../trunk/src_3rd/genht/hash.h gerb/gexpr.h \
+ ../../trunk/src_3rd/genvector/vtd0.h gerb/gex.tab.h
+gex.tab.o: gerb/gex.tab.c gerb/gexpr.h \
+ ../../trunk/src_3rd/genvector/vtd0.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h gerb/gex.tab.h
+gexpr.o: gerb/gexpr.c ../../trunk/config.h gerb/gexpr.h \
+ ../../trunk/src_3rd/genvector/vtd0.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h gerb/gex.tab.h
+camv_gui.o: gui/camv_gui.c ../../trunk/config.h ../../trunk/src/event.h \
+ ../../trunk/src/unit.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/hidlib.h \
+ ../../trunk/src/actions.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/libfungw/fungw.h ../../trunk/src_3rd/genht/htpp.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/hidlib_conf.h \
+ ../../trunk/src/conf.h ../../trunk/src/pcb-printf.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/genvector/vtp0.h ../../trunk/src/list_conf.h \
+ ../../trunk/src/compat_misc.h ../../trunk/src/compat_fs.h data.h \
+ ../../trunk/src/global_typedefs.h camv_typedefs.h \
+ ../../trunk/src/color.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h plug_io_act.h gui/layersel.h \
+ ../../trunk/src/dolists.h
+layersel.o: gui/layersel.c ../../trunk/config.h \
+ ../../trunk/src_3rd/genvector/vti0.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src_3rd/genvector/vtp0.h ../../trunk/src/hid.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src_3rd/genht/htsp.h \
+ ../../trunk/src_3rd/genht/ht.h ../../trunk/src/error.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h \
+ ../../trunk/src_3rd/genvector/gds_char.h ../../trunk/src/hid_cfg.h \
+ ../../trunk/src/hid.h ../../trunk/src/hid_dad.h \
+ ../../trunk/src/compat_misc.h ../../trunk/src/hid_attrib.h \
+ ../../trunk/src/pcb-printf.h ../../trunk/src/hid_dad_spin.h \
+ ../../trunk/src/actions.h ../../trunk/src_3rd/libfungw/fungw.h \
+ ../../trunk/src_3rd/genht/htpp.h data.h \
+ ../../trunk/src/global_typedefs.h camv_typedefs.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/color.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h ../../trunk/src/event.h \
+ ../../trunk/src/hidlib.h ../../trunk/src/layer.h \
+ ../../trunk/src/layer_grp.h ../../trunk/src/layer_ui.h \
+ ../../trunk/src/layer_vis.h ../../trunk/src/hidlib_conf.h \
+ ../../trunk/src/conf.h ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src/list_conf.h gui/layersel.h
+io_tedax.o: tedax/io_tedax.c ../../trunk/config.h \
+ ../../trunk/src_3rd/genht/htsp.h ../../trunk/src_3rd/genht/ht.h \
+ ../../trunk/src_3rd/genht/hash.h camv_typedefs.h plug_io.h data.h \
+ ../../trunk/src/global_typedefs.h ../../trunk/src/pcb_bool.h \
+ ../../trunk/src/unit.h camv_typedefs.h ../../trunk/src/hidlib.h \
+ ../../trunk/src/color.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src_3rd/genvector/genvector_impl.h \
+ ../../trunk/src_3rd/genvector/genvector_undef.h \
+ ../../trunk/src_3rd/genvector/vtp0.h rtree.h \
+ ../../trunk/src_3rd/genrtree/genrtree_api.h data.h \
+ ../../trunk/src/error.h tedax/parse.h ../../trunk/src/safe_fs.h \
+ ../../trunk/src/conf.h ../../trunk/src/pcb-printf.h \
+ ../../trunk/src_3rd/genvector/gds_char.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/dom.h \
+ ../../trunk/src_3rd/liblihata/lihata.h \
+ ../../trunk/src_3rd/liblihata/parser.h ../../trunk/src/list_conf.h \
+ ../../trunk/src_3rd/genlist/gentdlist_undef.h \
+ ../../trunk/src_3rd/genlist/gentdlist_impl.h \
+ ../../trunk/src_3rd/genlist/gendlist.h ../../trunk/src/compat_misc.h \
+ ../../trunk/src/misc_util.h obj_any.h obj_common.h ../../trunk/src/hid.h \
+ ../../trunk/src/error.h ../../trunk/src/attrib.h ../../trunk/src/layer.h \
+ ../../trunk/src/globalconst.h ../../trunk/src/color.h \
+ ../../trunk/src/obj_common.h ../../trunk/src/flag.h \
+ ../../trunk/src/data_parent.h ../../trunk/src/obj_arc_list.h \
+ ../../trunk/src/obj_arc.h ../../trunk/src_3rd/genlist/gendlist.h \
+ ../../trunk/src/obj_line_list.h ../../trunk/src/obj_line.h \
+ ../../trunk/src/obj_poly_list.h ../../trunk/src/obj_poly.h \
+ ../../trunk/src/polyarea.h ../../trunk/src/obj_text_list.h \
+ ../../trunk/src/obj_text.h ../../trunk/src/font.h \
+ ../../trunk/src_3rd/genht/htip.h ../../trunk/src/box.h \
+ ../../trunk/src/math_helper.h ../../trunk/src/misc_util.h obj_arc.h \
+ obj_line.h obj_poly.h ../../trunk/src/vtc0.h obj_grp.h
+parse.o: tedax/parse.c ../../trunk/config.h tedax/parse.h \
+ ../../trunk/src/error.h ../../trunk/src/global_typedefs.h \
+ ../../trunk/src/pcb_bool.h ../../trunk/src/unit.h \
+ ../../trunk/src/compat_misc.h
Index: trunk/src/Makefile.depgen
===================================================================
--- trunk/src/Makefile.depgen (nonexistent)
+++ trunk/src/Makefile.depgen (revision 1)
@@ -0,0 +1,36 @@
+
+# Autogenerated - DO NOT EDIT
+
+TRUNK=../../trunk
+HIDLIB_ROOT=$(TRUNK)
+include $(TRUNK)/src/hidlib.mak
+CFLAGS = -Wall -g -I. $(CFLAGS_HIDLIB)
+
+all:
+ echo "### Generated file, do not edit, run make dep ###" > Makefile.dep
+ echo "" >> Makefile.dep
+ gcc -MM camv-rnd.c $(CFLAGS) >> Makefile.dep
+ gcc -MM conf_core.c $(CFLAGS) >> Makefile.dep
+ gcc -MM crosshair.c $(CFLAGS) >> Makefile.dep
+ gcc -MM data.c $(CFLAGS) >> Makefile.dep
+ gcc -MM draw.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gui_act.c $(CFLAGS) >> Makefile.dep
+ gcc -MM obj_any.c $(CFLAGS) >> Makefile.dep
+ gcc -MM obj_arc.c $(CFLAGS) >> Makefile.dep
+ gcc -MM obj_grp.c $(CFLAGS) >> Makefile.dep
+ gcc -MM obj_line.c $(CFLAGS) >> Makefile.dep
+ gcc -MM obj_poly.c $(CFLAGS) >> Makefile.dep
+ gcc -MM plug_io.c $(CFLAGS) >> Makefile.dep
+ gcc -MM plug_io_act.c $(CFLAGS) >> Makefile.dep
+ gcc -MM rtree.c $(CFLAGS) >> Makefile.dep
+ gcc -MM excellon/excellon.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gerb/gedraw.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gerb/gedump.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gerb/geparse.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gerb/gerb2camv.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gerb/gex.tab.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gerb/gexpr.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gui/camv_gui.c $(CFLAGS) >> Makefile.dep
+ gcc -MM gui/layersel.c $(CFLAGS) >> Makefile.dep
+ gcc -MM tedax/io_tedax.c $(CFLAGS) >> Makefile.dep
+ gcc -MM tedax/parse.c $(CFLAGS) >> Makefile.dep
Index: trunk/src/camv-rnd-conf.lht
===================================================================
--- trunk/src/camv-rnd-conf.lht (nonexistent)
+++ trunk/src/camv-rnd-conf.lht (revision 1)
@@ -0,0 +1,29 @@
+li:pcb-rnd-conf-v1 {
+ ha:overwrite {
+ ha:rc {
+ li:preferred_gui = { gtk2_gl; gtk2_gdk; lesstif; batch }
+ hid_fallback = 1
+ }
+ ha:appearance {
+ ha:loglevels {
+ debug_tag = {}
+ debug_popup = false
+ info_tag = {}
+ info_popup = false
+ warning_tag = {}
+ warning_popup = true
+ error_tag = {}
+ error_popup = true
+ }
+ ha:color {
+ li:layer = {
+ {#8b2323}; {#3a5fcd}; {#104e8b}; {#cd3700}; {#548b54};
+ {#8b7355}; {#00868b}; {#228b22}; {#8b2323}; {#3a5fcd};
+ {#104e8b}; {#cd3700}; {#548b54}; {#8b7355}; {#00868b};
+ {#228b22};
+ }
+ }
+ }
+ }
+}
+
Index: trunk/src/camv-rnd-menu.lht
===================================================================
--- trunk/src/camv-rnd-menu.lht (nonexistent)
+++ trunk/src/camv-rnd-menu.lht (revision 1)
@@ -0,0 +1,96 @@
+ha:{
+ li:mouse {
+ li:left {
+ li:press = { Mode(Notify) }
+ li:press-shift = { Mode(Notify) }
+ li:press-ctrl = { Mode(Notify) }
+ li:release = { Mode(Release) }
+ li:release-shift = { Mode(Release) }
+ li:release-ctrl = { Mode(Release) }
+ }
+ li:middle {
+ li:press = { Pan(1) }
+ li:release = { Pan(0) }
+ }
+ li:right {
+ li:press = { Mode(Stroke) }
+ li:release = { Mode(Release); Popup(popup-obj, obj-type) }
+ li:shift-release = { Popup(popup-obj-misc) }
+ li:press-ctrl = { Display(CycleCrosshair) }
+ }
+ li:scroll-up {
+ li:press = { Zoom(0.8) }
+ li:press-shift = { Scroll(up) }
+ li:press-ctrl = { Scroll(left) }
+ }
+ li:scroll-down {
+ li:press = { Zoom(1.25) }
+ li:press-shift = { Scroll(down) }
+ li:press-ctrl = { Scroll(right) }
+ }
+ }
+
+ # List of tool names for the toolbar.
+ # Do not specify keys here, they are specified in the menu; the GUI will
+ # not pick up keys from this subtree. There's also no action here: the
+ # plugin handling this subtree will always pick the tool.
+ li:toolbar_static {
+ ha:via {tip={place a via on the board}}
+ ha:line {tip={draw a line segment (trace) on the board}}
+ ha:arrow {tip={switch to arrow mode}}
+ }
+
+ li:main_menu {
+ ### File Menu
+ ha:File {
+ li:submenu {
+ ha:New = { li:a={{f;n}; {Ctrln};}; action=New() }
+ ha:Load... = { a={f;o}; action=Load() }
+ ha:Quit = { a={f;q}; action=Quit() }
+ }
+ }
+
+ ha:View {
+ li:submenu {
+ ha:Current layer {
+ li:submenu {
+ ha:Move up { li:a={{l;u}; {l;Up};}; action=Layer(up) }
+ ha:Move down { li:a={{l;d}; {l;Down};}; action=Layer(down) }
+ ha:Move to top { li:a={{l;t}; {l;Page_Up};}; action=Layer(top) }
+ ha:Move to bottom { li:a={{l;b}; {l;Page_Down};}; action=Layer(bottom) }
+ ha:Add from file... { li:a={{l;a}; {l;+};}; action=Load(Layer) }
+ ha:Remove { li:a={{l;r}; {l;-};}; action=Layer(remove) }
+ }
+ }
+ }
+ }
+
+ ha:Window {
+ li:submenu {
+ ha:Message Log = { a={w;m}; action=LogDialog() }
+ }
+ }
+
+ ha:Help {
+ li:submenu {
+ ha:About = { action=About() }
+ }
+ }
+ } #main_menu
+
+ li:popups {
+# context sensitive right click: popup per object type under the cursor
+
+ ha:layer {
+ li:submenu {
+ ha:Move up { action=Layer(up) }
+ ha:Move down { action=Layer(down) }
+ ha:Move to top { action=Layer(top) }
+ ha:Move to bottom { action=Layer(bottom) }
+ ha:Add from file... { action=Load(Layer) }
+ ha:Remove { action=Layer(remove) }
+ }
+ }
+ } #popups
+
+} # root
Index: trunk/src/camv-rnd.c
===================================================================
--- trunk/src/camv-rnd.c (nonexistent)
+++ trunk/src/camv-rnd.c (revision 1)
@@ -0,0 +1,203 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include
+#include
+
+/* hidlib headers */
+#include "unit.h"
+#include "hid_init.h"
+#include "hid.h"
+#include "conf.h"
+#include "buildin.hidlib.h"
+#include "compat_misc.h"
+#include "plugins.h"
+
+/* local (app) headers */
+#include "gui_act.h"
+#include "data.h"
+#include "plug_io.h"
+#include "conf_core.h"
+
+static const char *EXPERIMENTAL = "The code is in alpha testing state yet.";
+
+const char *pcb_hidlib_default_embedded_menu = "";
+const char *conf_internal = "";
+const char *pcbhl_menu_file_paths[] = { "./", "~/.camv-rnd/", NULL };
+const char *pcbhl_menu_name_fmt = "camv-rnd-menu.lht";
+
+#define CAMV_RND_VERSION "0.1.0"
+#define CAMVSHAREDIR "/usr/share/camv-rnd"
+#define CONF_USER_DIR "~/.camv-rnd"
+const char *pcbhl_conf_userdir_path = CONF_USER_DIR;
+const char *pcphl_conf_user_path = CONF_USER_DIR "/camv-rnd-conf.lht";
+
+#if 0
+const char *pcbhl_conf_sysdir_path = CAMVSHAREDIR;
+const char *pcbhl_conf_sys_path = CAMVSHAREDIR "/camv-rnd-conf.lht";
+#else
+TODO("fix conf")
+/* temporary hack for running from ./ without internal version of the conf */
+const char *pcbhl_conf_sysdir_path = "./";
+const char *pcbhl_conf_sys_path = "./camv-rnd-conf.lht";
+#endif
+
+const char *pcbhl_app_package = "camv-rnd";
+const char *pcbhl_app_version = CAMV_RND_VERSION;
+const char *pcbhl_app_url = "http://repo.hu/projects/camv-rnd";
+
+void pcb_tool_gui_init(void)
+{
+
+}
+
+static void gui_support_plugins(int load)
+{
+ static int loaded = 0;
+ static pup_plugin_t *puphand;
+
+ if (load && !loaded) {
+ static const char *plugin_name = "camv-dialogs";
+ int state = 0;
+ loaded = 1;
+ pcb_message(PCB_MSG_DEBUG, "Loading GUI support plugin: '%s'\n", plugin_name);
+ puphand = pup_load(&pcb_pup, (const char **)pcb_pup_paths, plugin_name, 0, &state);
+ if (puphand == NULL)
+ pcb_message(PCB_MSG_ERROR, "Error: failed to load GUI support plugin '%s'\n-> expect missing widgets and dialog boxes\n", plugin_name);
+ }
+ if (!load && loaded && (puphand != NULL)) {
+ pup_unload(&pcb_pup, puphand, NULL);
+ loaded = 0;
+ puphand = NULL;
+ }
+}
+
+/* action table number of columns for a single action */
+static const char *camv_action_args[] = {
+/*short, -long, action, help, hint-on-error */
+ NULL, "-show-actions", "PrintActions()", "Print all available actions (human readable) and exit", NULL,
+ NULL, "-dump-actions", "DumpActions()", "Print all available actions (script readable) and exit", NULL,
+ NULL, "-dump-plugins", "DumpPlugins()", "Print all available plugins (script readable) and exit", NULL,
+ NULL, "-dump-plugindirs", "DumpPluginDirs()", "Print directories plugins might be loaded from and exit", NULL,
+ NULL, "-dump-oflags", "DumpObjFlags()", "Print object flags and exit", NULL,
+ NULL, "-show-paths", "PrintPaths()", "Print all configured paths and exit", NULL,
+ "V", "-version", "PrintVersion()", "Print version info and exit", NULL,
+ "V", "-dump-version", "DumpVersion()", "Print version info in script readable format and exit", NULL,
+ NULL, "-copyright", "PrintCopyright()", "Print copyright and exit", NULL,
+ NULL, NULL, NULL, NULL, NULL /* terminator */
+};
+
+static void camv_main_uninit(void)
+{
+ gui_support_plugins(0);
+ camv_design_free_fields(&camv);
+}
+
+static void camv_main_init(void)
+{
+ camv_plug_io_act_init();
+}
+
+int main(int argc, char *argv[])
+{
+ int n;
+ pcbhl_main_args_t ga;
+ char *command_line_file = NULL;
+
+ pcb_fix_locale();
+
+ pcbhl_main_args_init(&ga, argc, camv_action_args);
+
+
+ pcb_hidlib_init1(conf_core_init);
+ for(n = 1; n < argc; n++)
+ n += pcbhl_main_args_add(&ga, argv[n], argv[n+1]);
+ pcb_hidlib_init2(pup_buildins);
+
+ gui_act_init();
+ camv_main_init();
+ camv_gui_init();
+ conf_set(CFR_CLI, "editor/view/flip_y", 0, "1", POL_OVERWRITE);
+
+ if (pcbhl_main_args_setup1(&ga) != 0) {
+ camv_main_uninit();
+ pcbhl_main_args_uninit(&ga);
+ exit(1);
+ }
+
+/* Initialize actions only when the gui is already known so only the right
+ one is registered (there can be only one GUI). */
+TODO("action list");
+/*#include "generated_lists.h"*/
+
+TODO("replace this with fungw builtins")
+ camv_tdx_init();
+ camv_gerb_init();
+ camv_exc_init();
+
+ if (pcbhl_main_args_setup2(&ga, &n) != 0) {
+ camv_main_uninit();
+ pcbhl_main_args_uninit(&ga);
+ exit(n);
+ }
+
+ for(n = 0; ga.hid_argc > 0; n++, ga.hid_argc--) {
+ if (camv_io_load(&camv, ga.hid_argv[n]) != 0) {
+ pcb_message(PCB_MSG_ERROR, "Can not load file '%s' (specified on command line) for exporting or printing\n", command_line_file);
+ pcbhl_log_print_uninit_errs("Export load error");
+ exit(1);
+ }
+ }
+
+ if (pcbhl_main_exported(&ga, &camv.hidlib, camv_is_empty(&camv))) {
+ camv_main_uninit();
+ pcbhl_main_args_uninit(&ga);
+ exit(0);
+ }
+
+
+ TODO("should be conf'd");
+ camv.hidlib.grid = PCB_MM_TO_COORD(1);
+
+
+ /* main loop */
+ do {
+ if (PCB_HAVE_GUI_ATTR_DLG)
+ gui_support_plugins(1);
+ if (EXPERIMENTAL != NULL) {
+ pcb_message(PCB_MSG_ERROR, "******************************** IMPORTANT ********************************\n");
+ pcb_message(PCB_MSG_ERROR, "This revision of camv-rnd is experimental, unstable, do NOT attempt to use\n");
+ pcb_message(PCB_MSG_ERROR, "it for production. The reason for this state is:\n");
+ pcb_message(PCB_MSG_ERROR, "%s\n", EXPERIMENTAL);
+ pcb_message(PCB_MSG_ERROR, "******************************** IMPORTANT ********************************\n");
+ }
+ pcbhl_mainloop_interactive(&ga, &camv.hidlib);
+ } while(pcb_gui != NULL);
+
+ camv_main_uninit();
+ pcbhl_main_args_uninit(&ga);
+ return 0;
+}
Index: trunk/src/camv_typedefs.h
===================================================================
--- trunk/src/camv_typedefs.h (nonexistent)
+++ trunk/src/camv_typedefs.h (revision 1)
@@ -0,0 +1,9 @@
+#ifndef CAMV_TYPEDEFS_H
+#define CAMV_TYPEDEFS_H
+
+typedef struct camv_design_s camv_design_t;
+typedef struct camv_layer_s camv_layer_t;
+typedef union camv_any_obj_u camv_any_obj_t;
+typedef struct camv_grp_s camv_grp_t;
+
+#endif
Index: trunk/src/conf_core.c
===================================================================
--- trunk/src/conf_core.c (nonexistent)
+++ trunk/src/conf_core.c (revision 1)
@@ -0,0 +1,37 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+#include "conf_core.h"
+
+conf_core_t conf_core;
+
+void conf_core_init()
+{
+#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \
+ conf_reg_field(conf_core, field,isarray,type_name,cpath,cname,desc,flags);
+#include "conf_core_fields.h"
+}
Index: trunk/src/conf_core.h
===================================================================
--- trunk/src/conf_core.h (nonexistent)
+++ trunk/src/conf_core.h (revision 1)
@@ -0,0 +1,19 @@
+#ifndef CAMV_CONF_CORE_H
+#define CAMV_CONF_CORE_H
+
+#include "conf.h"
+#include "color.h"
+
+typedef struct {
+ struct { /* appearance */
+ struct { /* color */
+ CFT_COLOR layer[16]; /* default layer colors; when a new layer is created, a color from this list is assigned initially */
+ } color;
+ } appearance;
+} conf_core_t;
+
+
+void conf_core_init();
+extern conf_core_t conf_core;
+
+#endif
Index: trunk/src/conf_core_fields.h
===================================================================
--- trunk/src/conf_core_fields.h (nonexistent)
+++ trunk/src/conf_core_fields.h (revision 1)
@@ -0,0 +1 @@
+conf_reg(appearance.color.layer, array, CFN_COLOR, "appearance/color", "layer", "default layer colors; when a new layer is created, a color from this list is assigned initially", 0)
Index: trunk/src/crosshair.c
===================================================================
--- trunk/src/crosshair.c (nonexistent)
+++ trunk/src/crosshair.c (revision 1)
@@ -0,0 +1,72 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include
+
+#include "event.h"
+#include "hidlib_conf.h"
+#include "grid.h"
+#include "hid.h"
+
+#include "data.h"
+
+void pcb_hidlib_adjust_attached_objects(void)
+{
+
+}
+
+void *pcb_hidlib_crosshair_suspend(void)
+{
+ return NULL;
+}
+
+void pcb_hidlib_crosshair_restore(void *susp_data)
+{
+}
+
+void pcb_hidlib_crosshair_move_to(pcb_coord_t abs_x, pcb_coord_t abs_y, int mouse_mot)
+{
+ /* grid fit */
+ abs_x = pcb_grid_fit(abs_x, camv.hidlib.grid, camv.hidlib.grid_ox);
+ abs_y = pcb_grid_fit(abs_y, camv.hidlib.grid, camv.hidlib.grid_ox);
+ camv.crosshair_x = abs_x;
+ camv.crosshair_y = abs_y;
+
+ /* update the GUI */
+ pcb_gui->notify_crosshair_change(pcb_gui, pcb_false);
+ pcb_gui->set_crosshair(pcb_gui, abs_x, abs_y, 0);
+ pcb_gui->notify_crosshair_change(pcb_gui, pcb_true);
+}
+
+void pcbhl_draw_marks(pcb_hidlib_t *hidlib, pcb_bool inhibit_drawing_mode)
+{
+
+}
+
+void pcbhl_draw_attached(pcb_hidlib_t *hidlib, pcb_bool inhibit_drawing_mode)
+{
+
+}
Index: trunk/src/data.c
===================================================================
--- trunk/src/data.c (nonexistent)
+++ trunk/src/data.c (revision 1)
@@ -0,0 +1,173 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+
+#include "event.h"
+
+#include "data.h"
+#include "obj_any.h"
+#include "box.h"
+#include "conf_core.h"
+
+camv_design_t camv;
+
+void camv_layer_init(camv_layer_t *layer)
+{
+ memset(layer, 0, sizeof(camv_layer_t));
+ camv_rtree_init(&layer->objs);
+ layer->vis = 1;
+}
+
+camv_layer_t *camv_layer_new(void)
+{
+ camv_layer_t *res = malloc(sizeof(camv_layer_t));
+ camv_layer_init(res);
+ return res;
+}
+
+void camv_layer_append_to_design(camv_design_t *camv, camv_layer_t *layer)
+{
+ assert(layer->parent == NULL);
+ vtp0_append(&camv->layers, layer);
+ layer->parent = camv;
+}
+
+
+void camv_layer_invent_color(camv_design_t *camv, camv_layer_t *layer)
+{
+ static const int clrs = sizeof(conf_core.appearance.color.layer) / sizeof(conf_core.appearance.color.layer[0]);
+ static int next = 0;
+ int orig = next;
+ const pcb_color_t *clr;
+
+ do {
+ clr = &conf_core.appearance.color.layer[next];
+ next++;
+ if (next > clrs)
+ next = 0;
+ if (clr != NULL)
+ break;
+ } while(next != orig);
+
+ if (clr == NULL) {
+ pcb_color_load_str(&layer->color, "#000000");
+ pcb_message(PCB_MSG_ERROR, "Internal error: camv_layer_invent_color(): no color configured\n");
+ }
+ else
+ layer->color = *clr;
+}
+
+void camv_layer_free_fields(camv_layer_t *ly)
+{
+ void *o;
+ long n;
+ camv_rtree_it_t it;
+
+ free(ly->name); ly->name = NULL;
+
+ for(o = camv_rtree_all_first(&it, &ly->objs); o != NULL; o = camv_rtree_all_next(&it))
+ camv_obj_free(o);
+ camv_rtree_uninit(&ly->objs);
+
+ if (ly->parent != NULL) {
+ camv_design_t *camv = ly->parent;
+ /* optimization: go backward because the most common case is removing the last layer */
+ for(n = camv->layers.used - 1; n >= 0; n--) {
+ if (camv->layers.array[n] == ly) {
+ vtp0_remove(&camv->layers, n, 1);
+ break;
+ }
+ }
+ ly->parent = NULL;
+ }
+}
+
+void camv_layer_destroy(camv_layer_t *ly)
+{
+ camv_layer_free_fields(ly);
+ free(ly);
+}
+
+
+void camv_design_free_fields(camv_design_t *camv)
+{
+ long n;
+
+ /* optimization: go backward to avoid memmoves */
+ for(n = camv->layers.used - 1; n >= 0; n--)
+ camv_layer_destroy(camv->layers.array[n]);
+ vtp0_uninit(&camv->layers);
+}
+
+int camv_layer_set_vis(camv_design_t *camv, pcb_cardinal_t lid_, int vis, int emit_event)
+{
+ long lid;
+
+ if (lid_ >= camv->layers.used)
+ return -1;
+
+ /* find the main layer */
+ for(lid = lid_; (lid > 0) && (((camv_layer_t *)camv->layers.array[lid])->sub); lid--) ;
+
+
+ /* set main layer */
+ ((camv_layer_t *)camv->layers.array[lid])->vis = vis;
+
+ /* set all sublayers */
+ for(lid++; (lid < camv->layers.used) && (((camv_layer_t *)camv->layers.array[lid])->sub); lid++)
+ ((camv_layer_t *)camv->layers.array[lid])->vis = vis;
+
+ if (emit_event)
+ pcb_event(&camv->hidlib, PCB_EVENT_LAYERVIS_CHANGED, NULL);
+ return 0;
+}
+
+int camv_is_empty(camv_design_t *camv)
+{
+ long lid;
+
+ for(lid = 0; lid < camv->layers.used; lid++)
+ if (((camv_layer_t *)camv->layers.array[lid])->objs.size != 0)
+ return 0;
+ return 1;
+}
+
+void camv_data_bbox(camv_design_t *camv)
+{
+ long lid;
+
+ camv->bbox.x1 = camv->bbox.x2 = camv->bbox.y1 = camv->bbox.y2 = 0;
+ for(lid = 0; lid < camv->layers.used; lid++) {
+ camv_layer_t *ly = (camv_layer_t *)camv->layers.array[lid];
+ if (ly->objs.size != 0) {
+ pcb_box_bump_point((pcb_box_t *)&camv->bbox, ly->objs.bbox.x1, ly->objs.bbox.y1);
+ pcb_box_bump_point((pcb_box_t *)&camv->bbox, ly->objs.bbox.x2, ly->objs.bbox.y2);
+ }
+ }
+}
Index: trunk/src/data.h
===================================================================
--- trunk/src/data.h (nonexistent)
+++ trunk/src/data.h (revision 1)
@@ -0,0 +1,86 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_DATA_H
+#define CAMV_DATA_H
+
+#include "global_typedefs.h"
+#include "camv_typedefs.h"
+#include "hidlib.h"
+#include "color.h"
+#include "genvector/vtp0.h"
+#include "rtree.h"
+
+struct camv_design_s {
+ pcb_hidlib_t hidlib; /* shall be the first */
+
+ /* UI states */
+ pcb_coord_t crosshair_x, crosshair_y;
+
+ /* data */
+ vtp0_t layers; /* to camv_layer_t */
+ camv_rtree_box_t bbox;
+};
+
+struct camv_layer_s {
+ camv_rtree_t objs;
+ pcb_color_t color;
+ char *name;
+ camv_design_t *parent;
+
+ unsigned sub:1; /* if 1, layer is a sub-layer in compositing; a main layer is the first of a series of composite layers; sub layers are not visible in the layer sel */
+ unsigned vis:1; /* for main layers: UI visibility */
+ unsigned clearing:1; /* if 1, the layer is negative, clearing layer */
+};
+
+extern camv_design_t camv;
+
+void camv_layer_init(camv_layer_t *layer);
+camv_layer_t *camv_layer_new(void);
+
+void camv_layer_append_to_design(camv_design_t *camv, camv_layer_t *layer);
+
+/* Invent a layer color for a main layer that has non set explicitly */
+void camv_layer_invent_color(camv_design_t *camv, camv_layer_t *layer);
+
+/* If layer is part of a design, remove it. Destroy all layer objects
+ and free all memory allocated by the objects or the layer. */
+void camv_layer_free_fields(camv_layer_t *ly);
+
+/* Free all fields of layer and layer itself as well */
+void camv_layer_destroy(camv_layer_t *layer);
+
+int camv_layer_set_vis(camv_design_t *camv, pcb_cardinal_t lid, int vis, int emit_event);
+
+void camv_design_free_fields(camv_design_t *camv);
+
+int camv_is_empty(camv_design_t *camv);
+
+void camv_data_bbox(camv_design_t *camv);
+
+#define camv_hid_redraw(camv) pcb_gui->invalidate_all(pcb_gui)
+
+#endif
Index: trunk/src/depgen
===================================================================
--- trunk/src/depgen (nonexistent)
+++ trunk/src/depgen (revision 1)
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# temporary solution until we switch over to scconfig
+
+echo '
+# Autogenerated - DO NOT EDIT
+
+TRUNK=../../trunk
+HIDLIB_ROOT=$(TRUNK)
+include $(TRUNK)/src/hidlib.mak
+CFLAGS = -Wall -g -I. $(CFLAGS_HIDLIB)
+
+all:
+ echo "### Generated file, do not edit, run make dep ###" > Makefile.dep
+ echo "" >> Makefile.dep' > Makefile.depgen
+
+for fn in *.c */*.c
+do
+ echo " gcc -MM $fn \$(CFLAGS) >> Makefile.dep" >> Makefile.depgen
+done
\ No newline at end of file
Property changes on: trunk/src/depgen
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/src/draw.c
===================================================================
--- trunk/src/draw.c (nonexistent)
+++ trunk/src/draw.c (revision 1)
@@ -0,0 +1,91 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "hid.h"
+#include "obj_any.h"
+
+void camv_draw_layer(camv_layer_t *ly, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *region, pcb_xform_t *xform_caller)
+{
+ camv_rtree_it_t it;
+ void *o;
+
+ for(o = camv_rtree_first(&it, &ly->objs, (camv_rtree_box_t *)®ion->view); o != NULL; o = camv_rtree_next(&it)) {
+ camv_any_obj_t *obj = o;
+ obj->proto.calls->draw(obj, gc);
+ }
+}
+
+void pcbhl_expose_main(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *region, pcb_xform_t *xform_caller)
+{
+ pcb_cardinal_t lid;
+ pcb_hid_gc_t gc;
+ int clearing = -1, direct = 1, need_flush = 0;
+
+ gc = pcb_gui->make_gc(pcb_gui);
+
+ pcb_gui->set_color(gc, pcb_color_black);
+
+ /* calculate whether the cheaper direct-draw mechanism can be done */
+ for(lid = 0; lid < camv.layers.used; lid++) {
+ camv_layer_t *ly = camv.layers.array[lid];
+ if (!ly->vis) continue;
+ if (ly->clearing) {
+ direct = 0;
+ break;
+ }
+ }
+
+ /* announce start of rendering */
+ pcb_gui->render_burst(pcb_gui, PCB_HID_BURST_START, ®ion->view);
+
+ for(lid = 0; lid < camv.layers.used; lid++) {
+ camv_layer_t *ly = camv.layers.array[lid];
+ if (!ly->vis) continue;
+ if (!ly->sub) {
+ if (need_flush)
+ pcb_gui->set_drawing_mode(pcb_gui, PCB_HID_COMP_FLUSH, direct, ®ion->view);
+ pcb_gui->set_drawing_mode(pcb_gui, PCB_HID_COMP_RESET, direct, ®ion->view);
+ need_flush = 1;
+ }
+
+ if (((int)ly->clearing != clearing) || (!ly->sub)) {
+ clearing = ly->clearing;
+ pcb_gui->set_drawing_mode(pcb_gui, ly->clearing ? PCB_HID_COMP_NEGATIVE : PCB_HID_COMP_POSITIVE, direct, ®ion->view);
+ }
+ pcb_gui->set_color(gc, &ly->color);
+ camv_draw_layer(ly, gc, region, xform_caller);
+ }
+
+ if (need_flush)
+ pcb_gui->set_drawing_mode(pcb_gui, PCB_HID_COMP_FLUSH, direct, ®ion->view);
+ pcb_gui->render_burst(pcb_gui, PCB_HID_BURST_END, ®ion->view);
+ pcb_gui->destroy_gc(pcb_gui, gc);
+}
+
+void pcbhl_expose_preview(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *e)
+{
+
+}
Index: trunk/src/excellon/excellon.c
===================================================================
--- trunk/src/excellon/excellon.c (nonexistent)
+++ trunk/src/excellon/excellon.c (revision 1)
@@ -0,0 +1,421 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "error.h"
+#include "safe_fs.h"
+#include "compat_misc.h"
+#include "math_helper.h"
+
+#include "data.h"
+#include "plug_io.h"
+#include "obj_any.h"
+
+
+typedef struct {
+ /* static: set once in the header */
+ vtc0_t tools;
+ double metric_scale;
+ unsigned int has_metric_scale:1;
+ unsigned int inch:1;
+ unsigned int inbody:1;
+ unsigned int started:1; /* M48 detected */
+ unsigned int got_unit:1;
+
+ /* dynamic */
+ unsigned int rout:1;
+ unsigned int tool_down:1;
+ unsigned int eof:1; /* M30 */
+ pcb_coord_t x, y; /* current pos */
+ long tool;
+ camv_layer_t *ly;
+
+ /* parser */
+ long lineno;
+} exc_t;
+
+static void exc_gen_line(exc_t *exc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2)
+{
+ camv_any_obj_t *o = (camv_any_obj_t *)camv_line_new();
+ o->line.x1 = x1; o->line.y1 = y1;
+ o->line.x2 = x2; o->line.y2 = y2;
+ o->line.thick = exc->tools.array[exc->tool];
+ camv_obj_add_to_layer(exc->ly, o);
+}
+
+
+static inline pcb_coord_t exc2coord(exc_t *exc, double d)
+{
+ if (exc->inch)
+ return PCB_MIL_TO_COORD(d*1000.0);
+ return PCB_MM_TO_COORD(d);
+}
+
+static double exc_strtod(exc_t *exc, const char *str, char **end)
+{
+ const char *s;
+ int len, has_dot = 0;
+ double res = strtod(str, end);
+
+ for(s = str, len = 0; s < *end; s++,len++)
+ if (*s == '.')
+ has_dot = 1;
+
+ if (exc->inch && (len == 6) && !has_dot) {
+ /* old INCH format with no decimal point: 00.0000 format */
+ res /= 10000.0;
+ }
+ if (!exc->inch && exc->has_metric_scale && !has_dot) {
+ /* METRIC,00.000 flexible format */
+ res /= exc->metric_scale;
+ }
+ return res;
+}
+
+static int exc_parse_header(exc_t *exc, char **line)
+{
+ if ((*line)[0] == '%') {
+ (*line)++;
+ exc->inbody = 1;
+ return 0;
+ }
+
+ if (strcmp(*line, "M95") == 0) {
+ (*line) += 3;
+ exc->inbody = 1;
+ return 0;
+ }
+
+ if (strcmp(*line, "M48") == 0) {
+ (*line) += 3;
+ exc->started = 1;
+ return 0;
+ }
+
+ if ((strcmp(*line, "M30") == 0) || (strcmp(*line, "M00") == 0)) {
+ (*line) += 3;
+ exc->eof = 1;
+ return 0;
+ }
+
+ if (!exc->started) {
+ pcb_message(PCB_MSG_ERROR, "excellon: missing M48 before header comamnd %s\n", line);
+ return -1;
+ }
+
+ if (strncmp(*line, "METRIC", 6) == 0) {
+ (*line) += 6;
+ if (exc->got_unit)
+ goto err_unit_dup;
+ exc->inch = 0;
+ exc->got_unit = 1;
+ if ((*line)[0] == ',') {
+ char *sep;
+ int len;
+ (*line)++;
+ sep = strchr(*line, '.');
+ if (sep == NULL) {
+ pcb_message(PCB_MSG_ERROR, "excellon: metric format specifier lacks decimal dot\n");
+ return -1;
+ }
+ TODO("this expects newline");
+ len = strlen(*line);
+ len = len - (sep - (*line)) - 1;
+ exc->has_metric_scale = 1;
+ exc->metric_scale = pow(10, len);
+ (*line) += len;
+ }
+ return 0;
+ }
+
+ if (strncmp(*line, "INCH", 4) == 0) {
+ (*line) += 4;
+ if (exc->got_unit)
+ goto err_unit_dup;
+ exc->inch = 1;
+ exc->got_unit = 1;
+ return 0;
+ }
+
+ if ((*line)[0] == 'T') {
+ char *end;
+ long idx;
+ double d;
+ pcb_coord_t *td;
+
+ (*line)++;
+ idx = strtol(*line, &end, 10);
+ if (idx < 1) {
+ pcb_message(PCB_MSG_ERROR, "excellon: tool index out of range (0..99)\n");
+ return -1;
+ }
+ if (*end != 'C') {
+ pcb_message(PCB_MSG_ERROR, "excellon: tool separator 'C' is missing\n");
+ return -1;
+ }
+ *line = end+1;
+ d = strtod(*line, &end);
+ if (*end != '\0') {
+ pcb_message(PCB_MSG_ERROR, "excellon: invalid tool diameter\n");
+ return -1;
+ }
+ *line = end;
+ td = vtc0_get(&exc->tools, idx, 1);
+ if (td == NULL) {
+ pcb_message(PCB_MSG_ERROR, "excellon: failed to allocate tool id %ld\n", idx);
+ return -1;
+ }
+ *td = exc2coord(exc, d);
+ return 0;
+ }
+
+ pcb_message(PCB_MSG_ERROR, "excellon: invalid line '%s' in header\n", line);
+ return -1;
+
+ err_unit_dup:;
+ pcb_message(PCB_MSG_ERROR, "excellon: unit already set\n");
+ return -1;
+}
+
+static int exc_parse_move(exc_t *exc, char **line, char endchar)
+{
+ double x, y;
+ if (**line != 'X') {
+ pcb_message(PCB_MSG_ERROR, "excellon: expected X\n");
+ return -1;
+ }
+ (*line)++;
+ x = exc_strtod(exc, *line, line);
+
+ if (**line != 'Y') {
+ pcb_message(PCB_MSG_ERROR, "excellon: expected Y (broken X coord?)\n");
+ return -1;
+ }
+ (*line)++;
+ y = exc_strtod(exc, *line, line);
+
+ if (endchar != '\0') { /* requested specific termination */
+ if (**line != endchar) {
+ pcb_message(PCB_MSG_ERROR, "excellon: broken Y coord\n");
+ return -1;
+ }
+ }
+
+ exc->x = exc2coord(exc, x);
+ exc->y = exc2coord(exc, y);
+ return 0;
+}
+
+static int exc_parse_line(exc_t *exc, char **line)
+{
+ pcb_coord_t x0 = exc->x, y0 = exc->y;
+
+ if (exc->tool == 0) {
+ pcb_message(PCB_MSG_ERROR, "excellon: can not drill: no tool selected\n");
+ return -1;
+ }
+
+ if (exc_parse_move(exc, line, '\0') != 0)
+ return -1;
+ exc_gen_line(exc, x0, y0, exc->x, exc->y);
+ return 0;
+}
+
+static int exc_parse_arc(exc_t *exc, char **line, int cw)
+{
+ pcb_coord_t x0 = exc->x, y0 = exc->y, r;
+ double a;
+ char *end;
+
+ if (exc->tool == 0) {
+ pcb_message(PCB_MSG_ERROR, "excellon: can not drill: no tool selected\n");
+ return -1;
+ }
+
+ if (exc_parse_move(exc, line, 'A') != 0)
+ return -1;
+ a = exc_strtod(exc, *line, &end);
+ if (*end != '\0') {
+ pcb_message(PCB_MSG_ERROR, "excellon: broken A coord\n");
+ return -1;
+ }
+ *line = end;
+ r = exc2coord(exc, a);
+ TODO("draw arc");
+ return -1;
+}
+
+static int exc_parse_body(exc_t *exc, char **line)
+{
+ int code;
+
+ if (exc->eof) {
+ pcb_message(PCB_MSG_ERROR, "excellon: command after M30: '%s'\n", line);
+ return -1;
+ }
+
+ code = ((*line)[1]-'0')*10 + ((*line)[2]-'0');
+
+ if ((*line)[0] == 'G') {
+ (*line)+=3;
+ switch(code) {
+ case 00: exc->rout = 1; return exc_parse_move(exc, line, '\0');
+ case 05: exc->rout = 0; return 0;
+ case 01: return exc_parse_line(exc, line);
+ case 85: return exc_parse_line(exc, line);
+ case 02: return exc_parse_arc(exc, line, 1);
+ case 03: return exc_parse_arc(exc, line, 0);
+ }
+ pcb_message(PCB_MSG_ERROR, "excellon: invalid G-code: %d\n", code);
+ return -1;
+ }
+
+ if ((*line)[0] == 'T') {
+ char *end;
+ long idx;
+ (*line)++;
+ idx = strtol(*line, &end, 10);
+ if ((idx < 1) || (idx >= exc->tools.used)) {
+ pcb_message(PCB_MSG_ERROR, "excellon: tool index out of range (0..99)\n");
+ return -1;
+ }
+ if (*end != '\0') {
+ pcb_message(PCB_MSG_ERROR, "excellon: broken tool selection\n");
+ return -1;
+ }
+ (*line) = end;
+ if (exc->tools.array[idx] == 0) {
+ pcb_message(PCB_MSG_ERROR, "excellon: invalid tool selection: %d is not specified\n", idx);
+ return -1;
+ }
+ exc->tool = idx;
+ return 0;
+ }
+
+ if ((*line)[0] == 'X') {
+ if (exc->tool == 0) {
+ pcb_message(PCB_MSG_ERROR, "excellon: can not drill: no tool selected\n");
+ return -1;
+ }
+ if (exc_parse_move(exc, line, '\0') != 0)
+ return -1;
+ exc_gen_line(exc, exc->x, exc->y, exc->x, exc->y);
+ return 0;
+ }
+
+ if ((*line)[0] == 'M') {
+ (*line) += 3;
+ switch(code) {
+ case 15: exc->tool_down = 1; return 0;
+ case 16: exc->tool_down = 0; return 0;
+ case 17: exc->tool_down = 0; return 0;
+ case 30: exc->eof = 1; return 0;
+ }
+ }
+
+ return -1;
+}
+
+int camv_exc_load(camv_design_t *camv, const char *fn, FILE *f)
+{
+ char *end, *line, line_[1024];
+ exc_t exc;
+ int res;
+
+ memset(&exc, 0, sizeof(exc));
+ exc.ly = camv_layer_new();
+ exc.ly->name = pcb_strdup(fn);
+ camv_layer_invent_color(camv, exc.ly);
+ camv_layer_append_to_design(camv, exc.ly);
+ vtc0_init(&exc.tools);
+
+ while((line = fgets(line_, sizeof(line_), f)) != NULL) {
+ exc.lineno++;
+
+ while(isspace(*line)) line++;
+ end = strpbrk(line, "\n\r");
+ if (end == NULL) {
+ pcb_message(PCB_MSG_ERROR, "%s:%ld: Every line needs to be terminated by a newline character\n", fn, exc.lineno);
+ return -1;
+ }
+ *end = '\0';
+
+ if (*line == '\0') continue; /* ignore empty lines */
+ if (*line == ';') continue; /* ignore comments */
+
+ while(*line != '\0') {
+ if (exc.inbody)
+ res = exc_parse_body(&exc, &line);
+ else
+ res = exc_parse_header(&exc, &line);
+
+ if (res != 0) {
+ pcb_message(PCB_MSG_ERROR, "(excellon error occured at %s:%ld)\n", fn, exc.lineno);
+ goto quit;
+ }
+ }
+ }
+
+ quit:;
+ vtc0_uninit(&exc.tools);
+ return res;
+}
+
+static int camv_exc_test_load(camv_design_t *camv, const char *fn, FILE *f)
+{
+ char *line, line_[1024];
+ int bad = 0;
+
+ while((line = fgets(line_, sizeof(line_), f)) != NULL) {
+ while(isspace(*line)) line++;
+ if (*line == ';')
+ continue;
+ if ((strncmp(line, "M48", 3) == 0) && (!isalnum(line[3])))
+ return 1;
+ bad++;
+ if (bad > 16)
+ return 0;
+ }
+ return 0;
+}
+
+
+static camv_io_t io_exc = {
+ "excellon", 90,
+ camv_exc_test_load,
+ camv_exc_load,
+ NULL
+};
+
+
+void camv_exc_init(void)
+{
+ camv_io_reg(&io_exc);
+}
Index: trunk/src/gerb/doc/cmd_support.txt
===================================================================
--- trunk/src/gerb/doc/cmd_support.txt (nonexistent)
+++ trunk/src/gerb/doc/cmd_support.txt (revision 1)
@@ -0,0 +1,38 @@
+Commands supported (lower case represent arguments)
+
+D01 draw (poly mode: draw contour, ignore aperture)
+D02 move
+D03 flash (poly mode: error)
+Dn (where n > 10) select aperture
+G01 interpolation: linear
+G02 interpolation: CW circular
+G03 interpolation: CCW circular
+G04 comment
+G36 poly mode: filled polygon mode on
+G37 poly mode: filled polygon mode off
+G54Dn (where n > 10) select aperture
+G70 set unit to INCH
+G71 set unit to MM
+G74 set single quadrant mode (arc)
+G75 set multi quadrant mode (arc)
+G90 switch to absolute coords
+G91 switch to relative coords
+Xc move X, absolute
+Yc move Y, absolute
+Ic move X, relative (arc)
+Jc move Y, relative (arc)
+%MOIN set unit to INCH
+%MOMM set unit to MM
+%FS..XcYc set coordinate format; supports 'L'/'T' and 'A'/'I'
+%ADD add aperture
+%LN layer name
+%LP (sub)layer polarity
+%SR step-and-repeat
+
+Not supported yet (TODO):
+ AM: (aperture macro)
+
+Not supported (need example):
+ G10 magnified linear interpolation
+ G11 magnified linear interpolation
+ G12 magnified linear interpolation
Index: trunk/src/gerb/doc/config.txt
===================================================================
--- trunk/src/gerb/doc/config.txt (nonexistent)
+++ trunk/src/gerb/doc/config.txt (revision 1)
@@ -0,0 +1,5 @@
+draw_aper_hole [bool] ?
+ Aperture holes clearly need to be flashed, but it's not clear whether they
+ need to be drawn in D01/D02 or not. If true, draw holes in D01/D02, if false
+ use them only for flashing.
+
Index: trunk/src/gerb/doc/links
===================================================================
--- trunk/src/gerb/doc/links (nonexistent)
+++ trunk/src/gerb/doc/links (revision 1)
@@ -0,0 +1,2 @@
+http://pcbdesign-now.blogspot.com/2012/06/gerber-for-beginners.html
+https://www.artwork.com/gerber/appl2.htm
Index: trunk/src/gerb/expr/Makefile
===================================================================
--- trunk/src/gerb/expr/Makefile (nonexistent)
+++ trunk/src/gerb/expr/Makefile (revision 1)
@@ -0,0 +1,11 @@
+TRUNK=../../../../trunk
+CFLAGS = -Wall -g -I.. -I$(TRUNK)/src -I$(TRUNK) -I$(TRUNK)/src_3rd
+
+main: main.o ../gex.tab.o ../gex.o $(TRUNK)/src_3rd/genvector/vtd0.o
+
+main.o: main.c ../gex.tab.h ../gex.h
+
+../gex.tab.c ../gex.tab.h: ../gex.y ../gex.h
+ cd ../.. && make gerbyacc
+
+
Index: trunk/src/gerb/expr/main.c
===================================================================
--- trunk/src/gerb/expr/main.c (nonexistent)
+++ trunk/src/gerb/expr/main.c (revision 1)
@@ -0,0 +1,55 @@
+#include
+#include
+#include "gexpr.h"
+#include "gex.tab.h"
+
+extern int gexparse(ge_expr_prglist_t *ctx);
+
+int gexlex(YYSTYPE *lval, ge_expr_prglist_t *ctx_)
+{
+ char tmp[128], *end;
+ int ti, c = getchar();
+ switch(c) {
+ case '(': case ')': case '+': case '-': case 'x': case '/': return c;
+ case '$':
+ c = getchar();
+ for(ti = 0; isdigit(c) && (ti < sizeof(tmp)-1); c = getchar(),ti++)
+ tmp[ti] = c;
+ tmp[ti] = '\0';
+ ungetc(c, stdin);
+ lval->idx = atoi(tmp);
+ return T_PARAM;
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': case '.':
+ for(ti = 0; (isdigit(c) || (c == '.')) && (ti < sizeof(tmp)-1); c = getchar(),ti++)
+ tmp[ti] = c;
+ tmp[ti] = '\0';
+ ungetc(c, stdin);
+ lval->num = strtod(tmp, &end);
+ return T_NUM;
+ case '\n': return 0;
+ }
+ return c;
+}
+
+int gexerror(ge_expr_prglist_t *ctx_, const char *msg)
+{
+ printf("ERROR: %s\n", msg);
+ return 0;
+}
+
+int main()
+{
+ ge_expr_prglist_t lst;
+ vtd0_t params;
+ double res;
+
+ memset(&lst, 0, sizeof(ge_expr_prglist_t));
+ gexparse(&lst);
+
+ vtd0_init(¶ms);
+ printf("eval: %d\n", gex_eval(lst.first, ¶ms, &res));
+ printf("res: %f\n", res);
+ return 0;
+}
+
Index: trunk/src/gerb/gedraw.c
===================================================================
--- trunk/src/gerb/gedraw.c (nonexistent)
+++ trunk/src/gerb/gedraw.c (revision 1)
@@ -0,0 +1,107 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer - low level gerber parser
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+
+#define GVT_DONT_UNDEF
+#include "gedraw.h"
+#include
+#undef GVT_DONT_UNDEF
+
+#include "geparse.h"
+
+gedraw_inst_t *gedraw_alloc(gedraw_ctx_t *ctx, long line, long col)
+{
+ gedraw_inst_t *i;
+ i = vtgd_alloc_append(&ctx->code, 1);
+ i->line = line;
+ i->col = col;
+ return i;
+}
+
+void gedraw_dump_inst(FILE *f, gedraw_ctx_t *ctx, gedraw_inst_t *i)
+{
+ fprintf(f, "[%04d %04ld.%02ld] ", i - ctx->code.array, i->line, i->col);
+ switch(i->cmd) {
+ case GEC_invalid: fprintf(f, "invalid\n"); break;
+ case GEC_MACRO_DEF: fprintf(f, "MACRO_DEF %s\n", i->data.aper.data.macro.name); break;
+ case GEC_APER_DEF: fprintf(f, "APER_DEF %ld\n", i->data.aper.id); break;
+ case GEC_APER_SEL: fprintf(f, "APER_SEL %ld\n", i->data.id); break;
+ case GEC_DRAW: fprintf(f, "DRAW\n"); break;
+ case GEC_MOVE: fprintf(f, "MOVE\n"); break;
+ case GEC_FLASH: fprintf(f, "FLASH\n"); break;
+ case GEC_DO: fprintf(f, "DO\n"); break;
+ case GEC_SET_X: fprintf(f, "X %f mm\n", i->data.coord / 1000000.0); break;
+ case GEC_SET_Y: fprintf(f, "Y %f mm\n", i->data.coord / 1000000.0); break;
+ case GEC_SET_I: fprintf(f, "I %f mm\n", i->data.coord / 1000000.0); break;
+ case GEC_SET_J: fprintf(f, "J %f mm\n", i->data.coord / 1000000.0); break;
+ case GEC_SET_RELCRD: fprintf(f, "RELCRD %s\n", i->data.on ? "on" : "off"); break;
+ case GEC_SET_POLCLR: fprintf(f, "POLCLR %s\n", i->data.on ? "clear" : "draw"); break;
+ case GEC_SET_POLY: fprintf(f, "POLY %s\n", i->data.on ? "on" : "off"); break;
+ case GEC_SET_RELAT: fprintf(f, "RELAT %s\n", i->data.on ? "on" : "off"); break;
+ case GEC_SET_INTERP:
+ switch(i->data.interp) {
+ case GEI_LIN: fprintf(f, "INTERP linear\n"); break;
+ case GEI_CW: fprintf(f, "INTERP cw\n"); break;
+ case GEI_CCW: fprintf(f, "INTERP ccw\n"); break;
+ }
+ break;
+ case GEC_SET_QUADR:
+ switch(i->data.quadr) {
+ case GEQ_INVALID:fprintf(f, "QUADR !!!invalid!!!\n"); break;
+ case GEQ_SINGLE: fprintf(f, "QUADR single\n"); break;
+ case GEQ_MULTI: fprintf(f, "QUADR multi\n"); break;
+ }
+ break;
+ case GEC_STEPREP:
+ if (i->data.steprep.end)
+ fprintf(f, "STEPREP end\n");
+ else
+ fprintf(f, "STEPREP %d;%d %f;%f\n", i->data.steprep.x, i->data.steprep.y, i->data.steprep.i / 1000000.0, i->data.steprep.j / 1000000.0);
+ break;
+ }
+}
+
+void gedraw_dump_code(FILE *f, gedraw_ctx_t *ctx)
+{
+ gedraw_inst_t *i;
+ size_t n;
+ for(n = 0, i = ctx->code.array; n < ctx->code.used; n++,i++)
+ gedraw_dump_inst(f, ctx, i);
+}
+
+void gedraw_free(gedraw_ctx_t *ctx)
+{
+ gedraw_inst_t *i;
+ size_t n;
+ for(n = 0, i = ctx->code.array; n < ctx->code.used; n++,i++)
+ if (i->cmd == GEC_APER_DEF)
+ vtd0_uninit(&i->data.aper.data.macro.param);
+
+ vtgd_uninit(&ctx->code);
+}
Index: trunk/src/gerb/gedraw.h
===================================================================
--- trunk/src/gerb/gedraw.h (nonexistent)
+++ trunk/src/gerb/gedraw.h (revision 1)
@@ -0,0 +1,205 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer - low level gerber parser
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef GEDRAW_H
+#define GEDRAW_H
+
+#include
+#include
+#include
+#include
+#include "genvector/vtp0.h"
+
+#include "global_typedefs.h"
+#include "vtc0.h"
+#include "gexpr.h"
+
+typedef pcb_coord_t ge_coord_t; /* nanometer */
+typedef pcb_angle_t ge_angle_t; /* degree */
+
+typedef enum {
+ GEP_NEXT, /* all fine, read the next char */
+ GEP_END, /* all fine, end of stream */
+ GEP_ERROR /* stop reading */
+} ge_parse_res_t;
+
+typedef enum {
+ GEU_NONE = 0,
+ GEU_INCH,
+ GEU_MM
+} ge_unit_t;
+
+typedef enum {
+ GEA_CIRC,
+ GEA_RECT,
+ GEA_OBLONG,
+ GEA_POLY,
+ GEA_MACRO
+} ge_aper_shape_t;
+
+typedef enum {
+ GEMO_CIRC = 1,
+ GEMO_POLY = 4,
+ GEMO_REGPOLY = 5,
+ GEMO_MOIRE = 6,
+ GEMO_THERM = 7,
+ GEMO_LINE_XY = 20,
+ GEMO_LINE_WH = 21,
+
+ GEMO_SET /* this one doesn't have a numeric code but it is really just an instruction; operant[0] is target param idx, operand[1] is the expression */
+} ge_macro_op_t;
+
+typedef struct ge_macro_line_s ge_macro_line_t;
+struct ge_macro_line_s {
+ ge_macro_op_t op; /* operator: type of primitive */
+ vtp0_t operand; /* each entry is the first item of a linked list of a (ge_expr_prg_t *) */
+ int idx; /* only for GEMO_SET: target index, so it doesn't need to be converted to an expression */
+ ge_macro_line_t *next;
+};
+
+typedef struct ge_aper_macro_s {
+ ge_macro_line_t *line1; /* frist line of a singly linked list of macro lines to execute in order */
+ ge_macro_line_t *last; /* last line of a singly linked list of macro lines (for cheap append) */
+ int argc;
+ double *argv;
+} ge_aper_macro_t;
+
+typedef struct {
+ ge_aper_shape_t shape; /* macro aper doesn't have it */
+ ge_coord_t hole; /* macro aper doesn't have it */
+ union {
+ struct {
+ ge_coord_t dia;
+ } circ;
+ struct {
+ ge_coord_t xs, ys;
+ } rect;
+ struct {
+ ge_coord_t xs, ys;
+ } oblong;
+ struct {
+ ge_coord_t dia, corners;
+ ge_angle_t rot;
+ } poly;
+ struct {
+ const char *name; /* allocated in the macro hash (as key) */
+ const ge_aper_macro_t *am; /* allocated in the macro hash (as value) */
+ vtd0_t param; /* only for aperture def */
+ } macro;
+ } data;
+ long id;
+ void *cached; /* optional: generated/cached prototype, specific ot the drawing code */
+} ge_aper_t;
+
+typedef enum { /* interpolation mode */
+ GEI_LIN = 0, /* linear (default) */
+ GEI_CW, /* circular, clock-wise */
+ GEI_CCW /* circular, counter-clock-wise */
+} ge_interp_t;
+
+typedef enum { /* circular interpolation quadrants */
+ GEQ_INVALID = 0, /* default: invalid, yields error */
+ GEQ_SINGLE, /* span must be less than 90 deg */
+ GEQ_MULTI /* span may be more than 90 deg */
+} ge_quadr_t;
+
+typedef struct {
+ int x, y; /* x and y repeat */
+ ge_coord_t i, j;
+ int end; /* coords are invalid */
+} ge_steprep_t;
+
+typedef enum { /* field to use */
+ GEC_invalid = 0,
+ GEC_MACRO_DEF, /* -> aper */
+ GEC_APER_DEF, /* -> aper */
+ GEC_APER_SEL, /* -> id */
+ GEC_DRAW, /* n/a */
+ GEC_MOVE, /* n/a */
+ GEC_FLASH, /* n/a */
+ GEC_DO, /* n/a */
+ GEC_STEPREP, /* -> steprep */
+ GEC_SET_X, /* -> coord */
+ GEC_SET_Y, /* -> coord */
+ GEC_SET_I, /* -> coord */
+ GEC_SET_J, /* -> coord */
+ GEC_SET_RELCRD, /* -> on (relative coordinates) */
+ GEC_SET_POLCLR, /* -> on (polarity; when on, clear instead of draw (negative polarity)) */
+ GEC_SET_POLY, /* -> on */
+ GEC_SET_RELAT, /* -> on */
+ GEC_SET_INTERP, /* -> interp */
+ GEC_SET_QUADR /* -> quadr */
+} gedraw_cmd_t;
+
+typedef struct {
+ gedraw_cmd_t cmd;
+ union {
+ ge_aper_t aper;
+ ge_coord_t coord;
+ int on;
+ long id;
+ ge_interp_t interp;
+ ge_quadr_t quadr;
+ ge_steprep_t steprep;
+ } data;
+
+ long line, col; /* location in the input file for error messages */
+} gedraw_inst_t;
+
+#define GVT(x) vtgd_ ## x
+#define GVT_ELEM_TYPE gedraw_inst_t
+#define GVT_SIZE_TYPE size_t
+#define GVT_DOUBLING_THRS 4096
+#define GVT_START_SIZE 32
+#define GVT_FUNC
+#define GVT_SET_NEW_BYTES_TO 0
+
+#include
+#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size)
+#define GVT_FREE(vect, ptr) free(ptr)
+#include
+
+typedef struct {
+ pcb_coord_t acceptable_error; /* depends on coord precision determined by the parser */
+ unsigned aper_inited:1; /* aperutre hash initialized */
+ unsigned poly_closed:1; /* set by the contour append code if current polyline is closed at the moment (curos is at starting point) */
+ ge_interp_t interp;
+ ge_quadr_t quadr;
+ htip_t aper;
+ vtgd_t code;
+ vtc0_t contour;/* polygon drawing state */
+ pcb_coord_t ox, oy; /* rendering origin - 0;0 for the main drawing, modified by SR */
+} gedraw_ctx_t;
+
+gedraw_inst_t *gedraw_alloc(gedraw_ctx_t *ctx, long line, long col);
+
+void gedraw_dump_inst(FILE *f, gedraw_ctx_t *ctx, gedraw_inst_t *i);
+void gedraw_dump_code(FILE *f, gedraw_ctx_t *ctx);
+
+void gedraw_free(gedraw_ctx_t *ctx);
+
+
+#endif
Index: trunk/src/gerb/gedump.c
===================================================================
--- trunk/src/gerb/gedump.c (nonexistent)
+++ trunk/src/gerb/gedump.c (revision 1)
@@ -0,0 +1,69 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer - low level gerber parser
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include
+#include
+#include
+#include
+#include "geparse.h"
+#include "error.h"
+
+/*** hidlib emulation (glue) ***/
+void pcb_message(enum pcb_message_level ignored, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
+
+/*** parser ***/
+static int ge_getchar(geparse_ctx_t *ctx)
+{
+ return fgetc(stdin);
+}
+
+
+int main()
+{
+ geparse_ctx_t ctx;
+ ge_parse_res_t res;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.getchar = ge_getchar;
+ while((res = geparse(&ctx)) == GEP_NEXT) ;
+ if (res == GEP_ERROR) {
+ fprintf(stderr, "parse error at %ld:%ld: %s\n", ctx.line, ctx.col, ctx.errmsg);
+ geparse_free(&ctx);
+ return 1;
+ }
+
+ gedraw_dump_code(stderr, &ctx.draw);
+
+ geparse_free(&ctx);
+ return 0;
+}
Index: trunk/src/gerb/geparse.c
===================================================================
--- trunk/src/gerb/geparse.c (nonexistent)
+++ trunk/src/gerb/geparse.c (revision 1)
@@ -0,0 +1,1002 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer - low level gerber parser
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "geparse.h"
+#include "gedraw.h"
+#include "gexpr.h"
+#include "gex.tab.h"
+#include "error.h"
+
+#include "compat_misc.h"
+
+/* valid polygon aperture corners */
+#define POLY_MIN_CORNERS 3
+#define POLY_MAX_CORNERS 16
+
+/* valid coordinates can't take more than this number of characters in a string */
+#define MAX_COORD_STRLEN 16
+
+#define COMPILE(ctx, cmd_, field, arg) \
+ do { \
+ gedraw_inst_t *inst; \
+ inst = gedraw_alloc(&((ctx)->draw), (ctx)->line, (ctx)->col); \
+ inst->cmd = (cmd_); \
+ inst->data.field = arg; \
+ } while(0)
+
+#define COMPILE0(ctx, cmd_) \
+ do { \
+ gedraw_inst_t *inst; \
+ inst = gedraw_alloc(&((ctx)->draw), (ctx)->line, (ctx)->col); \
+ inst->cmd = (cmd_); \
+ } while(0)
+
+#define READ_(_ctx_, _res_, allow_eof) \
+ do { \
+ for(;;) { \
+ int _step_ = 0; \
+ if (_ctx_->ungetc != 0) { \
+ _res_ = _ctx_->ungetc; \
+ _ctx_->ungetc = 0; \
+ } \
+ else { \
+ _step_ = 1; \
+ _res_ = ctx->getchar(ctx); \
+ if ((_res_ < 32) && (_res_ != '\n') && (_res_ != '\r') && (_res_ != '\t')) { \
+ ctx->errmsg = "Invalid character (low binary)"; \
+ return GEP_ERROR; \
+ } \
+ else if (_res_ >= 127) { \
+ ctx->errmsg = "Invalid character (high binary)"; \
+ return GEP_ERROR; \
+ } \
+ } \
+ if (_step_) \
+ ctx->col++; \
+ if (_res_ == EOF) { \
+ if (!allow_eof) { \
+ ctx->errmsg = "Invalid command (first character is EOF)"; \
+ return GEP_ERROR; \
+ } \
+ break; \
+ } \
+ else if (_res_ == '\n') { \
+ if (_step_) { \
+ ctx->col = 0; \
+ ctx->line++; \
+ } \
+ } \
+ else if (_res_ == '\r') { \
+ } \
+ else \
+ break; \
+ } \
+ } while(0)
+
+#define UNGETC(_ctx_, _c_) \
+ do { \
+ if (_ctx_->ungetc != 0) { \
+ ctx->errmsg = "Internal error: multiple UNGETC calls"; \
+ return GEP_ERROR; \
+ } \
+ _ctx_->ungetc = _c_; \
+ } while(0)
+
+#define READ(_ctx_, _res_) READ_(_ctx_, _res_, 0)
+
+#define READ_NUM(_ctx_, _res_) \
+ do { \
+ int __sign__ = 1, __digc__, __dig__; \
+ _res_ = 0; \
+ for(__digc__ = 0;;__digc__++) { \
+ if (__digc__ > 10) { \
+ _ctx_->errmsg = "Number too long"; \
+ return GEP_ERROR; \
+ } \
+ READ(_ctx_, __dig__); \
+ if (__dig__ == '-') { \
+ if (__digc__ == 0) __sign__ = -1; \
+ else break;\
+ } \
+ else if (__dig__ == '+') { \
+ if (__digc__ == 0) __sign__ = +1; \
+ else break;\
+ } \
+ else if (isdigit(__dig__)) \
+ _res_ = _res_ * 10 + __dig__ - '0'; \
+ else \
+ break; \
+ } \
+ if (__sign__ < 0) \
+ _res_ = -_res_; \
+ UNGETC(_ctx_, __dig__); \
+ } while(0)
+
+/* read decimal into a char * buffer _res_; _len_inout_ is the maximum
+ length as input and actual length as output */
+#define READ_DEC_(_ctx_, _buf_, _len_inout_, _permit_decpt_) \
+ do { \
+ int __i__, __c__, __got_pt__ = 0; \
+ for(__i__ = 0;;__i__++) { \
+ if (__i__ >= _len_inout_-1) { \
+ _ctx_->errmsg = "Number too long"; \
+ return GEP_ERROR; \
+ } \
+ READ(_ctx_, __c__); \
+ _buf_[__i__] = __c__; \
+ if (__c__ == '-') { \
+ if (__i__ != 0) \
+ break;\
+ } \
+ else if (__c__ == '+') { \
+ if (__i__ != 0); \
+ break;\
+ } \
+ else if (_permit_decpt_ && (__c__ == '.')) { \
+ if (__got_pt__ == 0) __got_pt__ = 1; \
+ else break;\
+ } \
+ else if (!isdigit(__c__)) \
+ break; \
+ } \
+ _buf_[__i__] = '\0'; \
+ _len_inout_ = __i__; \
+ UNGETC(_ctx_, __c__); \
+ } while(0)
+
+/* parse decimal into double _res_ */
+#define READ_DEC(_ctx_, _res_) \
+ do { \
+ char __buf__[16]; \
+ int __len__ = sizeof(__buf__); \
+ READ_DEC_(_ctx_, __buf__, __len__, 1); \
+ _res_ = strtod(__buf__, NULL); \
+ } while(0)
+
+#define READ_COORD(_ctx_, _res_) \
+ do { \
+ char __buf__[3*MAX_COORD_STRLEN], *__start__ = __buf__+MAX_COORD_STRLEN; \
+ int __len__ = MAX_COORD_STRLEN, __need__ = _ctx_->cfmt_int + _ctx_->cfmt_fra, __save__, __has_sign__, __sign__; \
+ long __int__; \
+ double __fra__; \
+ READ_DEC_(_ctx_, __start__, __len__, 0); \
+ if (__need__ > 25) { \
+ _ctx_->errmsg = "Coordinate format too long"; \
+ return GEP_ERROR; \
+ } \
+ if ((_ctx_->cfmt_int < 1) || (_ctx_->cfmt_fra < 1)) { \
+ _ctx_->errmsg = "Coordinate format too short"; \
+ return GEP_ERROR; \
+ } \
+ __has_sign__ = (*__start__ == '-') || (*__start__ == '+'); \
+ __sign__ = *__start__; \
+ if (__len__ - __has_sign__ > __need__) { \
+ _ctx_->errmsg = "Coordinate longer than format permits"; \
+ return GEP_ERROR; \
+ } \
+ if (_ctx_->trailing_zero) { \
+ while(__len__ < __need__) { \
+ __buf__[__len__] = '0'; \
+ __len__++; \
+ } \
+ __buf__[__len__] = '\0'; \
+ } \
+ else { \
+ if (__has_sign__) \
+ __start__++;\
+ while(__len__ - __has_sign__ < __need__) { \
+ __start__--; \
+ *__start__ = '0'; \
+ __len__++; \
+ } \
+ if (__has_sign__) {\
+ __start__--; \
+ *__start__ = __sign__; \
+ } \
+ } \
+ __save__ = __start__[_ctx_->cfmt_int - 1 + __has_sign__]; \
+ __start__[_ctx_->cfmt_int - 1 + __has_sign__] = '.'; \
+ __fra__ = strtod(__start__ + _ctx_->cfmt_int + __has_sign__ - 1, NULL); \
+ __start__[_ctx_->cfmt_int - 1 + __has_sign__] = __save__; \
+ __start__[_ctx_->cfmt_int + __has_sign__] = '\0'; \
+ __int__ = strtol(__start__, NULL, 10); \
+ _res_ = ge_intfra_to_coord(_ctx_, __int__, __fra__, __has_sign__ && (__sign__ == '-')); \
+ } while(0)
+
+#define READ_ANGLE(_ctx_, _res_) READ_DEC(_ctx_, _res_)
+
+#define READ_COORD_DEC(_ctx_, _res_) \
+ do { \
+ double __tmp__; \
+ READ_DEC(_ctx_, __tmp__); \
+ _res_ = ge_double_to_coord(_ctx_, __tmp__); \
+ } while(0)
+
+
+#define READ_UPCASE(_ctx_, _res_) \
+ do { \
+ READ(_ctx_, _res_); \
+ if (!isupper(_res_)) { \
+ _ctx_->errmsg = "Unexpected uppercase alpha character"; \
+ return GEP_ERROR; \
+ } \
+ } while(0)
+
+#define READ_CMDEND(_ctx_) \
+ do { \
+ for(;;) { \
+ int __c__; \
+ READ(_ctx_, __c__); \
+ if (__c__ == '*') \
+ break;\
+ _ctx_->errmsg = "Unexpected character while looking for command terminator ('*')"; \
+ return GEP_ERROR; \
+ } \
+ } while(0)
+
+#define READ_LONGEND(_ctx_) \
+ do { \
+ for(;;) { \
+ int __c__; \
+ READ(_ctx_, __c__); \
+ if (__c__ == '%') \
+ break;\
+ _ctx_->errmsg = "Unexpected character while looking for long command terminator ('%')"; \
+ return GEP_ERROR; \
+ } \
+ } while(0)
+
+#define READ_TILL_CMDEND(_ctx_) \
+ do { \
+ for(;;) { \
+ int __c__; \
+ READ(_ctx_, __c__); \
+ if (__c__ == '*') \
+ break;\
+ } \
+ } while(0)
+
+#define READ_APERTURE(_ctx_, _aid_) \
+ do { \
+ int __c__; \
+ READ(_ctx_, __c__); \
+ if (__c__ != 'D') { \
+ _ctx_->errmsg = "Expected 'D' for aperture ID"; \
+ return GEP_ERROR; \
+ } \
+ READ_NUM(_ctx_, _aid_); \
+ } while(0)
+
+/* Append a macro name into a gds string, utnil endchr or '*' (endchr is not consumed) */
+#define READ_NAME_GDS(_ctx_, dst, endchr) \
+do { \
+ for(;;) { \
+ READ(ctx, c); \
+ if ((c == endchr) || (c == '*')) {\
+ UNGETC(_ctx_, c); \
+ break; \
+ } \
+ gds_append(&name, c); \
+ } \
+} while(0)
+
+static double ge_round(double x)
+{
+ return pcb_round(x);
+}
+
+ge_coord_t ge_double_to_coord(geparse_ctx_t *ctx, double d)
+{
+ switch(ctx->unit) {
+ case GEU_INCH:
+ return ge_round(d * 25400000.0);
+ case GEU_MM:
+ default:
+ return ge_round(d * 1000000.0);
+ }
+}
+
+ge_coord_t ge_intfra_to_coord(geparse_ctx_t *ctx, long int_part, double fra_part, int is_neg)
+{
+ ge_coord_t c;
+
+ if (int_part < 0)
+ int_part = -int_part;
+ c = ge_double_to_coord(ctx, (double)int_part + fra_part); /* lazy approach, slow but still accurate enough because of the magnitude of i and f */
+ return is_neg ? -c : c;
+}
+
+static ge_parse_res_t geparse_aperture_spec_shaped(geparse_ctx_t *ctx, long aid, int shape)
+{
+ int c;
+ gedraw_inst_t *inst = gedraw_alloc(&ctx->draw, ctx->line, ctx->col);
+
+ inst->data.aper.id = aid;
+ switch(shape) {
+ case 'C':
+ inst->data.aper.shape = GEA_CIRC;
+ READ_COORD_DEC(ctx, inst->data.aper.data.circ.dia);
+ READ(ctx, c);
+ if (c == '*')
+ break;
+ if (c != 'X') {
+ ctx->errmsg = "unexpected character in circle aperture def";
+ return GEP_ERROR;
+ }
+ READ_COORD_DEC(ctx, inst->data.aper.hole);
+
+ READ(ctx, c);
+ if (c == '*')
+ break;
+ ctx->errmsg = "unexpected character at the end of a circle aperture def";
+ return GEP_ERROR;
+
+ case 'R':
+ inst->data.aper.shape = GEA_RECT;
+ rect_cheat:;
+ READ_COORD_DEC(ctx, inst->data.aper.data.rect.xs);
+ READ(ctx, c);
+ if (c != 'X') {
+ ctx->errmsg = "unexpected character in rectangle aperture def after x-size";
+ return GEP_ERROR;
+ }
+ READ_COORD_DEC(ctx, inst->data.aper.data.rect.ys);
+ READ(ctx, c);
+ if (c == '*')
+ break;
+ if (c != 'X') {
+ ctx->errmsg = "unexpected character in rectangle aperture def";
+ return GEP_ERROR;
+ }
+ READ_COORD_DEC(ctx, inst->data.aper.hole);
+ READ(ctx, c);
+ if (c == '*')
+ break;
+ ctx->errmsg = "unexpected character at the end of a circle aperture def";
+ return GEP_ERROR;
+
+
+ case 'O':
+ inst->data.aper.shape = GEA_OBLONG;
+ goto rect_cheat; /* we can do this as long as the struct for the two are the same */
+ break;
+
+ case 'P':
+ inst->data.aper.shape = GEA_POLY;
+ READ_COORD_DEC(ctx, inst->data.aper.data.poly.dia);
+ READ(ctx, c);
+ if (c != 'X') {
+ ctx->errmsg = "unexpected character in polygon aperture def after diameter";
+ return GEP_ERROR;
+ }
+ READ_NUM(ctx, inst->data.aper.data.poly.corners);
+ READ(ctx, c);
+ if (c == '*')
+ goto poly_fin;
+ if (c != 'X') {
+ ctx->errmsg = "unexpected character in polygon aperture def (at angle)";
+ return GEP_ERROR;
+ }
+ READ_ANGLE(ctx, inst->data.aper.data.poly.rot);
+ READ(ctx, c);
+ if (c == '*')
+ goto poly_fin;
+ if (c != 'X') {
+ ctx->errmsg = "unexpected character in polygon aperture def (at hole)";
+ return GEP_ERROR;
+ }
+ READ_COORD_DEC(ctx, inst->data.aper.hole);
+ READ(ctx, c);
+
+ poly_fin:;
+ if (inst->data.aper.data.poly.corners < POLY_MIN_CORNERS) {
+ ctx->errmsg = "invalid polygon aperture: too few corners";
+ return GEP_ERROR;
+ }
+ if (inst->data.aper.data.poly.corners > POLY_MAX_CORNERS) {
+ ctx->errmsg = "invalid polygon aperture: too many corners";
+ return GEP_ERROR;
+ }
+ break;
+ default:
+ ctx->errmsg = "unsupported aperture shape (character)";
+ return GEP_ERROR;
+ }
+ READ_LONGEND(ctx);
+ inst->cmd = GEC_APER_DEF;
+ return GEP_NEXT;
+}
+
+/*** expression parsing ***/
+int gexerror(ge_expr_prglist_t *ctx_, const char *msg)
+{
+ geparse_ctx_t *ctx = ctx_->parent;
+ ctx->errmsg = msg;
+ return -1;
+}
+
+int gexlex(YYSTYPE *lval, ge_expr_prglist_t *ctx_)
+{
+ geparse_ctx_t *ctx = ctx_->parent;
+ int c;
+
+ READ(ctx, c);
+ switch(c) {
+ case ',':
+ case '%':
+ case '*':
+ UNGETC(ctx, c);
+ return 0;
+ case '$':
+ READ_NUM(ctx, lval->idx);
+ return T_PARAM;
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': case '.':
+ UNGETC(ctx, c);
+ READ_DEC(ctx, lval->num);
+ return T_NUM;
+ }
+ return c;
+}
+
+static int geparse_macro_expr(geparse_ctx_t *ctx, ge_expr_prg_t **res) {
+ int r;
+ ge_expr_prglist_t lst;
+
+ lst.first = lst.last = NULL;
+ lst.parent = ctx;
+
+ r = gexparse(&lst);
+ if (r == 0)
+ *res = lst.first;
+ else
+ *res = NULL;
+
+ return 0;
+}
+
+static ge_macro_line_t *macro_append(geparse_ctx_t *ctx, ge_aper_macro_t *am)
+{
+ ge_macro_line_t *line = calloc(sizeof(ge_macro_line_t), 1);
+ if (am->last != NULL) {
+ am->last->next = line;
+ am->last = line;
+ }
+ else
+ am->line1 = am->last = line;
+
+ return line;
+}
+
+static int geparse_macro_aperture_line(geparse_ctx_t *ctx, ge_aper_macro_t *am, int code, int argc)
+{
+ int c, a;
+ ge_macro_line_t *line = macro_append(ctx, am);
+
+ line->op = code;
+
+ for(a = 0; a < argc; a++) {
+ ge_expr_prg_t *e;
+ READ(ctx, c);
+ if (c != ',') {
+ ctx->errmsg = "macro aperture: missing comma (not enough parameters?)";
+ return -1;
+ }
+ geparse_macro_expr(ctx, &e);
+ vtp0_append(&line->operand, e);
+ }
+ READ_CMDEND(ctx);
+ return 0;
+}
+
+static int geparse_macro_aperture_poly(geparse_ctx_t *ctx, ge_aper_macro_t *am, int code)
+{
+ int c, a, numpts;
+ double er;
+ ge_expr_prg_t *e;
+ vtd0_t allzero;
+ ge_macro_line_t *line = macro_append(ctx, am);
+
+ line->op = code;
+
+ for(a = 0; a < 2; a++) {
+ READ(ctx, c);
+ if (c != ',') {
+ ctx->errmsg = "macro aperture: missing comma (not enough parameters?)";
+ return -1;
+ }
+ geparse_macro_expr(ctx, &e);
+ vtp0_append(&line->operand, e);
+ }
+
+ memset(&allzero, 0, sizeof(allzero));
+ if (gex_eval(e, &allzero, &er) != 0) {
+ ctx->errmsg = "macro aperture: failed to evaluate number of polygon points";
+ return -1;
+ }
+ numpts = pcb_round(er);
+
+ for(a = 0; a < numpts*2+3; a++) {
+ READ(ctx, c);
+ if (c != ',') {
+ ctx->errmsg = "macro aperture: missing comma (not enough points?)";
+ return -1;
+ }
+ geparse_macro_expr(ctx, &e);
+ vtp0_append(&line->operand, e);
+ }
+
+ READ_CMDEND(ctx);
+ return 0;
+}
+
+static int geparse_macro_aperture_set(geparse_ctx_t *ctx, ge_aper_macro_t *am)
+{
+ ge_expr_prg_t *e;
+ int idx, c;
+ double d;
+ ge_macro_line_t *line = macro_append(ctx, am);
+
+ READ_NUM(ctx, idx);
+ READ(ctx, c);
+ if (c != '=')
+ return -1;
+ line->op = GEMO_SET;
+ line->idx = idx;
+ geparse_macro_expr(ctx, &e);
+ vtp0_append(&line->operand, e);
+ READ_CMDEND(ctx);
+ return 0;
+}
+
+static ge_parse_res_t geparse_macro_aperture(geparse_ctx_t *ctx)
+{
+ gedraw_inst_t *inst;
+ ge_aper_macro_t *am;
+ int c = 0;
+ gds_t name;
+
+ /* read the name and check for dups */
+ gds_init(&name);
+ READ_NAME_GDS(ctx, &name, '*');
+ READ(ctx, c); /* remvoe the '*' */
+ if (htsp_has(ctx->macros, name.array)) {
+ gds_uninit(&name);
+ ctx->errmsg = "macro aperture: duplicate macro name";
+ return GEP_ERROR;
+ }
+
+ am = calloc(sizeof(ge_aper_macro_t), 1);
+ inst = gedraw_alloc(&ctx->draw, ctx->line, ctx->col);
+ inst->data.aper.data.macro.name = name.array;
+ inst->cmd = GEC_MACRO_DEF;
+ inst->data.aper.shape = GEA_MACRO;
+ inst->data.aper.data.macro.am = am;
+
+ htsp_set(ctx->macros, name.array, am);
+ /* do _not_ call gds_uninit(&name): alloction is now owned by the hash table */
+
+ for(;;) {
+ int code, lineres;
+ READ(ctx, c);
+ switch(c) {
+ case '$':
+ if (geparse_macro_aperture_set(ctx, am) != 0)
+ return GEP_ERROR;
+ continue;
+ case '%':
+ return GEP_NEXT; /* long command termination */
+ default:
+ UNGETC(ctx, c); /* would be a numeric code */
+ }
+ READ_NUM(ctx, code);
+ switch(code) {
+ case 0: /* comment */
+ READ_TILL_CMDEND(ctx);
+ lineres = 0;
+ break;
+ case GEMO_CIRC: lineres = geparse_macro_aperture_line(ctx, am, code, 5); break;
+ case GEMO_POLY: lineres = geparse_macro_aperture_poly(ctx, am, code); break;
+ case GEMO_REGPOLY: lineres = geparse_macro_aperture_line(ctx, am, code, 6); break;
+ case GEMO_MOIRE: lineres = geparse_macro_aperture_line(ctx, am, code, 9); break;
+ case GEMO_THERM: lineres = geparse_macro_aperture_line(ctx, am, code, 6); break;
+ case GEMO_LINE_XY: lineres = geparse_macro_aperture_line(ctx, am, code, 7); break;
+ case GEMO_LINE_WH: lineres = geparse_macro_aperture_line(ctx, am, code, 6); break;
+ default:
+ ctx->errmsg = "macro aperture: unknown primtive code";
+ return GEP_ERROR;
+ }
+ if (lineres != 0)
+ return GEP_ERROR;
+ }
+}
+
+#define CMD(c1, c2) ((((unsigned int)c1)<<8) | (((unsigned int)c2)))
+
+static ge_parse_res_t geparse_aperture_add(geparse_ctx_t *ctx)
+{
+ int c1, c2, c;
+ long aid;
+
+ READ_APERTURE(ctx, aid);
+ if (aid < 10) {
+ ctx->errmsg = "invalid aperture ID: must be at least 10";
+ return GEP_ERROR;
+ }
+ READ(ctx, c1);
+ READ(ctx, c2);
+ if (c2 != ',') { /* named macro */
+ char sep;
+ gds_t name;
+ htsp_entry_t *he;
+ ge_aper_macro_t *am;
+ gedraw_inst_t *inst;
+
+ gds_init(&name);
+ gds_append(&name, c1);
+ gds_append(&name, c2);
+ READ_NAME_GDS(ctx, &name, ',');
+
+ he = htsp_getentry(ctx->macros, name.array);
+ if (he == NULL) {
+ ctx->errmsg = "named aperture not found";
+ return GEP_ERROR;
+ }
+ am = he->value;
+ gds_uninit(&name);
+
+ inst = gedraw_alloc(&ctx->draw, ctx->line, ctx->col);
+ READ(ctx, sep);
+ while(sep != '*') {
+ double d;
+ READ_DEC(ctx, d);
+ vtd0_append(&inst->data.aper.data.macro.param, d);
+ READ(ctx, sep);
+ if ((sep != 'X') && (sep != '*')) {
+ vtd0_uninit(&inst->data.aper.data.macro.param);
+ ctx->errmsg = "aperture macro: invalid parameter separator: expected X or *";
+ return GEP_ERROR;
+ }
+ }
+
+ inst->cmd = GEC_APER_DEF;
+ inst->data.aper.shape = GEA_MACRO;
+ inst->data.aper.id = aid;
+ inst->data.aper.data.macro.name = he->key;
+ inst->data.aper.data.macro.am = am;
+
+ READ_LONGEND(ctx);
+ return GEP_NEXT;
+ }
+
+ /* simple, non-macro aperture */
+ return geparse_aperture_spec_shaped(ctx, aid, c1);
+}
+
+static ge_parse_res_t geparse_set_unit(geparse_ctx_t *ctx)
+{
+ int c1, c2;
+
+ READ_UPCASE(ctx, c1);
+ READ_UPCASE(ctx, c2);
+ switch(CMD(c1, c2)) {
+ case CMD('I', 'N'):
+ ctx->unit = GEU_INCH;
+ READ_CMDEND(ctx);
+ break;
+ case CMD('M', 'M'):
+ ctx->unit = GEU_MM;
+ READ_CMDEND(ctx);
+ break;
+ default:
+ ctx->errmsg = "invalid unit for %%MO";
+ return GEP_ERROR;
+ }
+
+ READ_LONGEND(ctx);
+ return GEP_NEXT;
+}
+
+static ge_parse_res_t geparse_steprep(geparse_ctx_t *ctx)
+{
+ int c;
+
+ gedraw_inst_t *inst = gedraw_alloc(&ctx->draw, ctx->line, ctx->col);
+ inst->cmd = GEC_STEPREP;
+ READ(ctx, c);
+ switch(c) {
+ case 'X':
+ inst->data.steprep.end = 0;
+ READ_NUM(ctx, inst->data.steprep.x);
+ READ(ctx, c); if (c != 'Y') goto steprep_err;
+ READ_NUM(ctx, inst->data.steprep.y);
+ READ(ctx, c); if (c != 'I') goto steprep_err;
+ READ_COORD_DEC(ctx, inst->data.steprep.i);
+ READ(ctx, c); if (c != 'J') goto steprep_err;
+ READ_COORD_DEC(ctx, inst->data.steprep.j);
+ READ(ctx, c); if (c != '*') goto steprep_err;
+ break;
+ case '*':
+ inst->data.steprep.end = 1;
+ break;
+ default:
+ ctx->errmsg = "unsupported SR parameter: must be empty or must start with X";
+ return GEP_ERROR;
+ }
+ READ_LONGEND(ctx);
+ return GEP_NEXT;
+
+ steprep_err:;
+ ctx->errmsg = "invalid %SR argument format";
+ return GEP_ERROR;
+}
+
+static ge_parse_res_t geparse_coordfmt(geparse_ctx_t *ctx)
+{
+ int c, x1, y1, x2, y2;
+
+ READ(ctx, c);
+ switch(c) {
+ case 'L': ctx->trailing_zero = 0; break;
+ case 'T': ctx->trailing_zero = 1; break;
+ default:
+ ctx->errmsg = "unsupported coord format: %FS zero padding character must be 'L' or 'T'";
+ return GEP_ERROR;
+ }
+ READ(ctx, c);
+ switch(c) {
+ case 'A': COMPILE(ctx, GEC_SET_RELCRD, on, 0); break;
+ case 'I': COMPILE(ctx, GEC_SET_RELCRD, on, 1); break;
+ default:
+ ctx->errmsg = "unsupported coord format: %FS coord reference character should be 'A' or 'I'";
+ return GEP_ERROR;
+ }
+ READ(ctx, c); if (c != 'X') goto bad_cmd;
+ READ(ctx, x1); if (!isdigit(x1)) goto bad_num;
+ READ(ctx, x2); if (!isdigit(x2)) goto bad_num;
+ READ(ctx, c); if (c != 'Y') goto bad_cmd;
+ READ(ctx, y1); if (!isdigit(y1)) goto bad_num;
+ READ(ctx, y2); if (!isdigit(y2)) goto bad_num;
+ READ_CMDEND(ctx);
+ if ((x1 != y1) || (x2 != y2)) {
+ ctx->errmsg = "unsupported coord format: %FS X and Y should be the same";
+ return GEP_ERROR;
+ }
+ ctx->cfmt_int = x1 - '0';
+ ctx->cfmt_fra = x2 - '0';
+
+ READ_LONGEND(ctx);
+ return GEP_NEXT;
+
+ bad_num:;
+ ctx->errmsg = "expected digit";
+ return GEP_ERROR;
+
+ bad_cmd:;
+ ctx->errmsg = "missing X or Y in coord format spec";
+ return GEP_ERROR;
+}
+
+ge_parse_res_t geparse_long_cmd(geparse_ctx_t *ctx)
+{
+ int c1, c2, c;
+
+ READ_UPCASE(ctx, c1);
+ READ_UPCASE(ctx, c2);
+ switch(CMD(c1, c2)) {
+ case CMD('M', 'O'):
+ return geparse_set_unit(ctx);
+
+ case CMD('S', 'R'):
+ return geparse_steprep(ctx);
+
+ case CMD('I', 'P'): /* image polarity - pos or neg */
+ READ(ctx, c);
+ switch(c) {
+ case 'P': /* positive is the default setup, no need to do anything */ break;
+ case 'N': pcb_message(PCB_MSG_WARNING, "IPNEG: negative image polarity is not yet supported:\nthe image will be displayed in inverse.\n"); break;
+ default: pcb_message(PCB_MSG_WARNING, "Invalid IP arg, assuming POS\n");
+ }
+ READ_TILL_CMDEND(ctx);
+ break;
+
+ case CMD('L', 'P'):
+ READ(ctx, c);
+ switch(c) {
+ case 'C': COMPILE(ctx, GEC_SET_POLCLR, on, 1); break;
+ case 'D': COMPILE(ctx, GEC_SET_POLCLR, on, 0); break;
+ }
+ READ_CMDEND(ctx);
+ COMPILE0(ctx, GEC_DO);
+ break;
+
+ case CMD('F', 'S'): /* coord format */
+ return geparse_coordfmt(ctx);
+
+ case CMD('A', 'D'): /* add aperture */
+ return geparse_aperture_add(ctx);
+
+ case CMD('A', 'M'): /* add macro aperture, up to and including the terminator % */
+ return geparse_macro_aperture(ctx);
+
+ case CMD('L', 'N'): /* layer name? -> ignore */
+ READ_TILL_CMDEND(ctx);
+ break;
+
+
+ default:
+ ctx->errmsg = "unrecognized long command";
+ return GEP_ERROR;
+ }
+
+ READ_LONGEND(ctx);
+ return GEP_NEXT;
+}
+#undef CMD
+
+#define CMD(chr, code) ((((unsigned int)chr)<<8)+code)
+ge_parse_res_t geparse_short_cmd(geparse_ctx_t *ctx, int cmd)
+{
+ ge_coord_t crd;
+ long code;
+ int c;
+
+
+ switch(cmd) { /* single char short commands */
+ case '*': COMPILE0(ctx, GEC_DO); return GEP_NEXT;
+ case 'X': READ_COORD(ctx, crd); COMPILE(ctx, GEC_SET_X, coord, crd); return GEP_NEXT;
+ case 'Y': READ_COORD(ctx, crd); COMPILE(ctx, GEC_SET_Y, coord, crd); return GEP_NEXT;
+ case 'I': READ_COORD(ctx, crd); COMPILE(ctx, GEC_SET_I, coord, crd); return GEP_NEXT;
+ case 'J': READ_COORD(ctx, crd); COMPILE(ctx, GEC_SET_J, coord, crd); return GEP_NEXT;
+ case 'D':
+ select_aper:;
+ READ_NUM(ctx, code);
+ if (code < 10)
+ goto d_cmd; /* these are not apertures but commands; code is already parsed */
+ READ_CMDEND(ctx);
+ COMPILE(ctx, GEC_APER_SEL, id, code);
+ return GEP_NEXT;
+ }
+
+ READ_NUM(ctx, code);
+ d_cmd:;
+ code += ((unsigned int)cmd) << 8;
+ switch(code) {
+ case CMD('G', 01): COMPILE(ctx, GEC_SET_INTERP, interp, GEI_LIN); return GEP_NEXT;
+ case CMD('G', 02): COMPILE(ctx, GEC_SET_INTERP, interp, GEI_CW); return GEP_NEXT;
+ case CMD('G', 03): COMPILE(ctx, GEC_SET_INTERP, interp, GEI_CCW); return GEP_NEXT;
+ case CMD('G', 04): READ_TILL_CMDEND(ctx); return GEP_NEXT;
+ case CMD('G', 36): READ_CMDEND(ctx); COMPILE(ctx, GEC_SET_POLY, on, 1); return GEP_NEXT;
+ case CMD('G', 37): READ_CMDEND(ctx); COMPILE(ctx, GEC_SET_POLY, on, 0); return GEP_NEXT;
+ case CMD('G', 54):
+ READ(ctx, c);
+ if (c != 'D') {
+ ctx->errmsg = "G54 requires a 'D'\n";
+ return GEP_ERROR;
+ }
+ goto select_aper;
+ case CMD('G', 70): READ_CMDEND(ctx); ctx->unit = GEU_INCH; return GEP_NEXT;
+ case CMD('G', 71): READ_CMDEND(ctx); ctx->unit = GEU_MM; return GEP_NEXT;
+ case CMD('G', 74): READ_CMDEND(ctx); COMPILE(ctx, GEC_SET_QUADR, interp, GEQ_SINGLE); return GEP_NEXT;
+ case CMD('G', 75): READ_CMDEND(ctx); COMPILE(ctx, GEC_SET_QUADR, interp, GEQ_MULTI); return GEP_NEXT;
+ case CMD('G', 90): COMPILE(ctx, GEC_SET_RELCRD, on, 0); return GEP_NEXT;
+ case CMD('G', 91): COMPILE(ctx, GEC_SET_RELCRD, on, 1); return GEP_NEXT;
+ case CMD('D', 01): COMPILE0(ctx, GEC_DRAW); return GEP_NEXT;
+ case CMD('D', 02): COMPILE0(ctx, GEC_MOVE); return GEP_NEXT;
+ case CMD('D', 03): COMPILE0(ctx, GEC_FLASH); return GEP_NEXT;
+ case CMD('M', 02): READ_CMDEND(ctx); ctx->at_end = 1; return GEP_END;
+ }
+ ctx->errmsg = "unknown short command code\n";
+ return GEP_ERROR;
+}
+#undef CMD
+
+
+static ge_parse_res_t geparse_(geparse_ctx_t *ctx)
+{
+ if (ctx->at_end)
+ return GEP_END;
+ if (ctx->line == 0)
+ ctx->line = 1;
+ for(;;) {
+ int c;
+
+ READ(ctx, c);
+ switch(c) {
+ case EOF:
+ if (ctx->cmd_cnt == 0) {
+ ctx->errmsg = "EOF before the first command";
+ return GEP_ERROR;
+ }
+ return GEP_END;
+ case '\n':
+ case '\r':
+ break;
+ case '%':
+ ctx->cmd_cnt++;
+ return geparse_long_cmd(ctx);
+ case 'D':
+ case 'G':
+ case 'M':
+ case 'X':
+ case 'Y':
+ case 'I':
+ case 'J':
+ case '*':
+ ctx->cmd_cnt++;
+ return geparse_short_cmd(ctx, c);
+ default:
+ ctx->errmsg = "Invalid command (first character)";
+ return GEP_ERROR;
+ }
+ }
+}
+
+ge_parse_res_t geparse(geparse_ctx_t *ctx)
+{
+ if (ctx->macros == NULL)
+ ctx->macros = htsp_alloc(strhash, strkeyeq);
+ return geparse_(ctx);
+}
+
+static void geparse_free_macro_aper(ge_aper_macro_t *am)
+{
+ ge_macro_line_t *l, *next;
+ for(l = am->line1; l != NULL; l = next) {
+ int a;
+ next = l->next;
+ for(a = 0; a < l->operand.used; a++)
+ gex_free_prg(l->operand.array[a]);
+ free(l->operand.array);
+ free(l);
+ }
+ free(am->argv);
+ free(am);
+}
+
+void geparse_free(geparse_ctx_t *ctx)
+{
+ gedraw_free(&ctx->draw);
+ if (ctx->macros != NULL) {
+ htsp_entry_t *e;
+ for(e = htsp_first(ctx->macros); e != NULL; e = htsp_next(ctx->macros, e)) {
+ free(e->key); /* name */
+ geparse_free_macro_aper(e->value);
+ }
+ htsp_free(ctx->macros);
+ }
+}
+
Index: trunk/src/gerb/geparse.h
===================================================================
--- trunk/src/gerb/geparse.h (nonexistent)
+++ trunk/src/gerb/geparse.h (revision 1)
@@ -0,0 +1,59 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer - low level gerber parser
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "gedraw.h"
+
+#include
+
+typedef struct geparse_ctx_s geparse_ctx_t;
+
+struct geparse_ctx_s {
+ /* public: parser state */
+ long line, col, cmd_cnt;
+ const char *errmsg;
+
+ /* public: caller provided functions */
+ int (*getchar)(geparse_ctx_t *ctx); /* read the next character from the stream */
+
+ /* public: data used only by the caller */
+ void *user_data;
+
+ /* private: parser state */
+ ge_unit_t unit;
+ int cfmt_int, cfmt_fra; /* coordinate format: integer and fraction digits */
+ int ungetc;
+ unsigned trailing_zero:1; /* coords are padded with trailing zeros */
+ unsigned at_end:1;
+
+ /* private: draw program */
+ gedraw_ctx_t draw;
+ htsp_t *macros; /* both key and values pointing into the bytecode */
+};
+
+
+ge_parse_res_t geparse(geparse_ctx_t *ctx);
+void geparse_free(geparse_ctx_t *ctx);
+
Index: trunk/src/gerb/gerb2camv.c
===================================================================
--- trunk/src/gerb/gerb2camv.c (nonexistent)
+++ trunk/src/gerb/gerb2camv.c (revision 1)
@@ -0,0 +1,1206 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "error.h"
+#include "safe_fs.h"
+#include "compat_misc.h"
+#include "rotate.h"
+#include "math_helper.h"
+#include "polygon1_gen.h"
+#include "polyarea.h"
+
+#include "data.h"
+#include "plug_io.h"
+#include "obj_any.h"
+
+#include "geparse.h"
+#include "gedraw.h"
+
+/*** low level draw ***/
+
+/* assumes dst is zero sized */
+static void pline2camv(camv_poly_t *dst, pcb_pline_t *src)
+{
+ pcb_pline_t *l;
+ pcb_vnode_t *v;
+ long n;
+
+ n = 0;
+ for(l = src; l != NULL; l = l->next) {
+ v = &l->head;
+#ifdef DONT_TRUST_COUNT
+ do {
+ n++;
+ v = v->next;
+ } while(v != &l->head);
+#else
+ n += l->Count;
+#endif
+/* printf("l cont=%d n=%ld\n", l->Count, n);*/
+ }
+
+
+ camv_poly_allocpts(dst, n);
+ n = 0;
+ for(l = src; l != NULL; l = l->next) {
+ v = &l->head;
+ do {
+ dst->x[n] = v->point[0];
+ dst->y[n] = v->point[1];
+ n++;
+ v = v->next;
+ } while(v != &l->head);
+ }
+}
+
+static void emit_build(pcb_pline_t *pl, void *ud)
+{
+ camv_grp_t *dst = ud;
+ camv_poly_t *opoly = (camv_poly_t *)&dst->objs[dst->len];
+ camv_poly_init(opoly);
+ pline2camv(opoly, pl);
+ dst->len++;
+}
+
+/* Returns a polygon or a group of polygons, free's src*/
+static camv_any_obj_t *polyarea2camv(pcb_polyarea_t *src)
+{
+ pcb_pline_t *l;
+ long holes = 0, islands = 0;
+ pcb_polyarea_t *pa;
+
+ pa = src;
+ do {
+ for(l = pa->contours->next; l != NULL; l = l->next) holes++;
+ islands++;
+ pa = pa->f;
+ } while(pa != src);
+
+ if (holes > 0) { /* has holes, dice and return a group of objects */
+ camv_grp_t *grp = camv_grp_new();
+ grp->len = 0;
+ grp->objs = calloc(sizeof(camv_any_obj_t), (holes+2)*2);
+ pcb_polyarea_no_holes_dicer(src, 0, 0, 0, 0, emit_build, grp); /* handles islands */
+ return (camv_any_obj_t *)grp;
+ }
+ else {
+ if (islands != 1) { /* multiple islands, no holes: need to create a group of camv polygons */
+ long i = 0;
+ camv_grp_t *grp = camv_grp_new();
+
+ grp->len = islands;
+ grp->objs = malloc(sizeof(camv_any_obj_t) * grp->len);
+ pa = src;
+ do {
+ camv_poly_t *dst = &grp->objs[i];
+ camv_poly_init(dst);
+ pline2camv(dst, pa->contours);
+ i++;
+ pa = pa->f;
+ } while(pa != src);
+ pcb_polyarea_free(&src);
+ return (camv_any_obj_t *)grp;
+ }
+ else { /* single island, no holes: return a sinlge camv poly */
+ camv_poly_t *dst = camv_poly_new();
+ pline2camv(dst, src->contours);
+ pcb_polyarea_free(&src);
+ return (camv_any_obj_t *)dst;
+ }
+ }
+}
+
+/* Convert an oblong aperture into a camv polygon around 0;0 */
+static camv_any_obj_t *aper_oblong2poly(ge_aper_t *aper, double rot)
+{
+ pcb_coord_t xh, yh;
+ pcb_polyarea_t *pa, *ph, *ptmp;
+ camv_any_obj_t *o;
+ int n;
+
+ TODO("figure if we need rotation");
+ xh = pcb_round((double)aper->data.oblong.xs / 2.0);
+ yh = pcb_round((double)aper->data.oblong.ys / 2.0);
+ if (xh > yh)
+ pa = pcb_poly_from_line(-xh+yh, 0, +xh-yh, 0, aper->data.oblong.ys, 0);
+ else
+ pa = pcb_poly_from_line(0, -yh+xh, 0, +yh-xh, aper->data.oblong.xs, 0);
+
+ /* subtract the hole if there's one */
+ if (aper->hole > 0) {
+ ph = pcb_poly_from_circle(0, 0, aper->hole/2);
+ pcb_polyarea_boolean_free(pa, ph, &ptmp, PCB_PBO_SUB);
+ pa = ptmp;
+ }
+
+ o = polyarea2camv(pa);
+ return o;
+}
+
+/* Convert a regular polygon with no hole aperture into a camv polygon around 0;0 */
+static camv_any_obj_t *aper_poly2poly_nohole(ge_aper_t *aper, double rot)
+{
+ camv_any_obj_t *o;
+ double r, a, as;
+ int n;
+
+ o = (camv_any_obj_t *)camv_poly_new();
+ camv_poly_allocpts(&o->poly, aper->data.poly.corners);
+ as = (360.0 / (double)aper->data.poly.corners) / PCB_RAD_TO_DEG;
+ r = (double)aper->data.poly.dia / 2.0;
+ for(n = 0, a = (rot + aper->data.poly.rot) / PCB_RAD_TO_DEG; n < aper->data.poly.corners; n++,a+=as) {
+ o->poly.x[n] = pcb_round(r * cos(a));
+ o->poly.y[n] = pcb_round(r * sin(a));
+ }
+ return o;
+}
+
+static pcb_polyarea_t *pa_regpoly(pcb_coord_t cx, pcb_coord_t cy, pcb_cardinal_t corners, pcb_coord_t dia, double rot)
+{
+ pcb_pline_t *contour;
+ pcb_vector_t v;
+ double r, a, as;
+ int n;
+
+ as = (360.0 / (double)corners) / PCB_RAD_TO_DEG;
+ r = (double)dia / 2.0;
+
+ for(n = 0, a = rot / PCB_RAD_TO_DEG; n < corners; n++, a+=as) {
+ v[0] = cx + pcb_round(r * cos(a));
+ v[1] = cy + pcb_round(r * sin(a));
+ if (n == 0)
+ contour = pcb_poly_contour_new(v);
+ else
+ pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v));
+ }
+
+ return pcb_poly_from_contour_autoinv(contour);
+}
+
+/* Convert a regular polygon with hole aperture into a camv polygon around 0;0 */
+static camv_any_obj_t *aper_poly2poly_hole(ge_aper_t *aper, double rot)
+{
+ pcb_polyarea_t *ps, *ph, *pres;
+
+ ps = pa_regpoly(0, 0, aper->data.poly.corners, aper->data.poly.dia, rot + aper->data.poly.rot);
+ ph = pcb_poly_from_circle(0, 0, aper->hole/2);
+ pcb_polyarea_boolean_free(ps, ph, &pres, PCB_PBO_SUB);
+
+ return polyarea2camv(pres);
+}
+
+/* idx is counted from 1 for code clarity */
+static int param_eval_int(const ge_macro_line_t *l, int paridx, vtd0_t *param)
+{
+ double res;
+ ge_expr_prg_t **prg = (ge_expr_prg_t **)vtp0_get((vtp0_t *)&l->operand, paridx-1, 0);
+ assert(prg != NULL); /* the parser should have checked argc already */
+ gex_eval(*prg, param, &res);
+ return pcb_round(res);
+}
+
+/* idx is counted from 1 for code clarity */
+static double param_eval_dbl(const ge_macro_line_t *l, int paridx, vtd0_t *param)
+{
+ double res;
+ ge_expr_prg_t **prg = (ge_expr_prg_t **)vtp0_get((vtp0_t *)&l->operand, paridx-1, 0);
+ assert(prg != NULL); /* the parser should have checked argc already */
+ gex_eval(*prg, param, &res);
+ return res;
+}
+
+/* idx is counted from 1 for code clarity */
+static pcb_coord_t param_eval_crd(const ge_macro_line_t *l, int paridx, vtd0_t *param)
+{
+ double res;
+ ge_expr_prg_t **prg = (ge_expr_prg_t **)vtp0_get((vtp0_t *)&l->operand, paridx-1, 0);
+ assert(prg != NULL); /* the parser should have checked argc already */
+ gex_eval(*prg, param, &res);
+TODO("respect ctx unit");
+ return (pcb_coord_t)PCB_MM_TO_COORD(res);
+}
+
+/* merge pb into dst (pol=0: clear, pol=1: draw) */
+static void macro_line_render_merge(pcb_polyarea_t **dst, pcb_polyarea_t *pb, int pol)
+{
+ pcb_polyarea_t *pa = *dst;
+
+ if (pa == NULL) {
+ if ((pb == NULL) || (!pol))
+ return;
+ *dst = pb;
+ }
+ else {
+ *dst = NULL;
+ pcb_polyarea_boolean_free(pa, pb, dst, pol ? PCB_PBO_UNITE : PCB_PBO_SUB);
+ }
+}
+
+static pcb_polyarea_t *pa_rect(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t x3, pcb_coord_t y3, pcb_coord_t x4, pcb_coord_t y4)
+{
+ pcb_vector_t v;
+ pcb_pline_t *pl;
+
+ v[0] = x1;
+ v[1] = y1;
+ pl = pcb_poly_contour_new(v);
+
+ v[0] = x2;
+ v[1] = y2;
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ v[0] = x3;
+ v[1] = y3;
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ v[0] = x4;
+ v[1] = y4;
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ return pcb_poly_from_contour_autoinv(pl);
+}
+
+static pcb_polyarea_t *pa_rect_rot(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t x3, pcb_coord_t y3, pcb_coord_t x4, pcb_coord_t y4, double cs, double sn)
+{
+ pcb_vector_t v;
+ pcb_pline_t *pl;
+
+ v[0] = x1;
+ v[1] = y1;
+ pcb_rotate(&v[0], &v[1], 0, 0, cs, sn);
+ pl = pcb_poly_contour_new(v);
+
+ v[0] = x2;
+ v[1] = y2;
+ pcb_rotate(&v[0], &v[1], 0, 0, cs, sn);
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ v[0] = x3;
+ v[1] = y3;
+ pcb_rotate(&v[0], &v[1], 0, 0, cs, sn);
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ v[0] = x4;
+ v[1] = y4;
+ pcb_rotate(&v[0], &v[1], 0, 0, cs, sn);
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ return pcb_poly_from_contour_autoinv(pl);
+}
+
+
+
+static pcb_polyarea_t *pa_ring(pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t d_outer, pcb_coord_t d_inner)
+{
+ pcb_polyarea_t *pbig, *psmall, *pout;
+
+ pbig = pcb_poly_from_circle(cx, cy, d_outer/2);
+ if (d_inner < 100)
+ return pbig;
+ psmall = pcb_poly_from_circle(cx, cy, d_inner/2);
+ pcb_polyarea_boolean_free(pbig, psmall, &pout, PCB_PBO_SUB);
+ return pout;
+}
+
+/* Render a single line (primitive) of a macro into an accumulating polyarea dst */
+static int macro_line_render(pcb_polyarea_t **dst, const ge_macro_line_t *l, vtd0_t *param, double rot)
+{
+ int pol, corners, n, maxrng;
+ pcb_coord_t x, y, d, th, x1, y1, x2, y2, od, id, rth, chth, chd, gap, w, h;
+ double r, vx, vy, nx, ny, len, cs, sn;
+ pcb_polyarea_t *pb, *pc, *pd;
+ pcb_vector_t v;
+ pcb_pline_t *contour;
+
+ switch(l->op) {
+ case GEMO_CIRC:
+ pol = param_eval_int(l, 1, param);
+ d = param_eval_crd(l, 2, param);
+ x = param_eval_crd(l, 3, param);
+ y = param_eval_crd(l, 4, param);
+ r = param_eval_dbl(l, 5, param) + rot;
+ if (r != 0)
+ pcb_rotate(&x, &y, 0, 0, cos(-r / PCB_RAD_TO_DEG), sin(-r / PCB_RAD_TO_DEG));
+ pb = pcb_poly_from_circle(x, y, d/2);
+ macro_line_render_merge(dst, pb, pol);
+ return 0;
+ case GEMO_POLY:
+ pol = param_eval_int(l, 1, param);
+ corners = param_eval_int(l, 2, param);
+ r = param_eval_dbl(l, l->operand.used, param) + rot;
+ cs = cos(-r / PCB_RAD_TO_DEG);
+ sn = sin(-r / PCB_RAD_TO_DEG);
+ v[0] = param_eval_crd(l, 3, param);
+ v[1] = param_eval_crd(l, 4, param);
+ pcb_rotate(&v[0], &v[1], 0, 0, cs, sn);
+ contour = pcb_poly_contour_new(v);
+ for(n = 1; n < corners; n++) {
+ v[0] = param_eval_crd(l, n*2+3, param);
+ v[1] = param_eval_crd(l, n*2+4, param);
+ pcb_rotate(&v[0], &v[1], 0, 0, cs, sn);
+ pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v));
+ }
+ pb = pcb_poly_from_contour_autoinv(contour);
+ macro_line_render_merge(dst, pb, pol);
+ return 0;
+ case GEMO_REGPOLY:
+ pol = param_eval_int(l, 1, param);
+ corners = param_eval_int(l, 2, param);
+ x = param_eval_crd(l, 3, param);
+ y = param_eval_crd(l, 4, param);
+ d = param_eval_crd(l, 5, param);
+ r = param_eval_dbl(l, 6, param) + rot;
+ if (r != 0)
+ pcb_rotate(&x, &y, 0, 0, cos(-r / PCB_RAD_TO_DEG), sin(-r / PCB_RAD_TO_DEG));
+ pb = pa_regpoly(x, y, corners, d, r);
+ macro_line_render_merge(dst, pb, pol);
+ return 0;
+ case GEMO_MOIRE:
+ x = x1 = param_eval_crd(l, 1, param);
+ y = y1 = param_eval_crd(l, 2, param);
+ od = param_eval_crd(l, 3, param);
+ rth = param_eval_crd(l, 4, param);
+ gap = param_eval_crd(l, 5, param);
+ maxrng = param_eval_int(l, 6, param);
+ chth = param_eval_crd(l, 7, param);
+ chd = param_eval_crd(l, 8, param);
+ r = param_eval_dbl(l, 9, param) + rot;
+ cs = cos(-r / PCB_RAD_TO_DEG);
+ sn = sin(-r / PCB_RAD_TO_DEG);
+ if (r != 0) {
+ pcb_rotate(&x1, &y1, 0, 0, cs, sn);
+ if ((x != 0) || (y != 0))
+ pcb_message(PCB_MSG_WARNING, "gerb: some gerber viewers (e.g. gerbv) won't render correctly rotated aperture macro primitive Moire when center is not 0;0\n");
+ }
+
+ /* crosshair */
+ chth /= 2;
+ chd /= 2;
+ pb = pa_rect_rot(x-chd, y-chth, x+chd, y-chth, x+chd, y+chth, x-chd, y+chth, cs, sn); /* horizontal */
+ pc = pa_rect_rot(x-chth, y-chd, x+chth, y-chd, x+chth, y+chd, x-chth, y+chd, cs, sn); /* vertical */
+ pcb_polyarea_boolean_free(pb, pc, &pd, PCB_PBO_UNITE);
+
+ /* accumulate rings in pd */
+ for(n = 0; (n < maxrng) && (od > 100); od -= gap*2 + rth*2, n++) {
+ pb = pa_ring(x1, y1, od, od-rth*2);
+ pc = pd;
+ pd = NULL;
+ pcb_polyarea_boolean_free(pb, pc, &pd, PCB_PBO_UNITE);
+ }
+
+ macro_line_render_merge(dst, pd, 1);
+ return 0;
+ case GEMO_THERM:
+ x = x1 = param_eval_crd(l, 1, param);
+ y = y1 = param_eval_crd(l, 2, param);
+ od = param_eval_crd(l, 3, param);
+ id = param_eval_crd(l, 4, param);
+ th = param_eval_crd(l, 5, param);
+ r = param_eval_dbl(l, 6, param) + rot;
+
+ cs = cos(-r / PCB_RAD_TO_DEG);
+ sn = sin(-r / PCB_RAD_TO_DEG);
+ if (r != 0) {
+ pcb_rotate(&x1, &y1, 0, 0, cs, sn);
+ if ((x != 0) || (y != 0))
+ pcb_message(PCB_MSG_WARNING, "gerb: some gerber viewers (e.g. gerbv) won't render correctly rotated aperture macro primitive therm when center is not 0;0\n");
+ }
+ pb = pa_ring(x1, y1, od, id);
+
+ th /= 2;
+ pc = pa_rect_rot(x-od, y-th, x+od, y-th, x+od, y+th, x-od, y+th, cs, sn); /* horizontal */
+ pcb_polyarea_boolean_free(pb, pc, &pd, PCB_PBO_SUB);
+
+ pc = pa_rect_rot(x-th, y-od, x+th, y-od, x+th, y+od, x-th, y+od, cs, sn); /* vertical */
+ pcb_polyarea_boolean_free(pd, pc, &pb, PCB_PBO_SUB);
+
+ macro_line_render_merge(dst, pb, 1);
+ return 0;
+ case GEMO_LINE_XY:
+ pol = param_eval_int(l, 1, param);
+ th = param_eval_crd(l, 2, param);
+ x1 = param_eval_crd(l, 3, param);
+ y1 = param_eval_crd(l, 4, param);
+ x2 = param_eval_crd(l, 5, param);
+ y2 = param_eval_crd(l, 6, param);
+ r = param_eval_dbl(l, 7, param) + rot;
+
+ line_xy:;
+ if (r != 0) {
+ r = -r;
+ pcb_rotate(&x1, &y1, 0, 0, cos(r / PCB_RAD_TO_DEG), sin(r / PCB_RAD_TO_DEG));
+ pcb_rotate(&x2, &y2, 0, 0, cos(r / PCB_RAD_TO_DEG), sin(r / PCB_RAD_TO_DEG));
+ }
+ vx = x2 - x1;
+ vy = y2 - y1;
+ nx = -vy;
+ ny = vx;
+ len = pcb_distance(x1, y1, x2, y2);
+ if (len == 0)
+ len = 1;
+ nx /= len;
+ ny /= len;
+
+ pb = pa_rect(
+ pcb_round(x1 - nx*th/2.0), pcb_round(y1 - ny*th/2.0),
+ pcb_round(x2 - nx*th/2.0), pcb_round(y2 - ny*th/2.0),
+ pcb_round(x2 + nx*th/2.0), pcb_round(y2 + ny*th/2.0),
+ pcb_round(x1 + nx*th/2.0), pcb_round(y1 + ny*th/2.0));
+ macro_line_render_merge(dst, pb, pol);
+ return 0;
+ case GEMO_LINE_WH:
+ pol = param_eval_int(l, 1, param);
+ w = param_eval_crd(l, 2, param);
+ h = param_eval_crd(l, 3, param);
+ x = param_eval_crd(l, 4, param);
+ y = param_eval_crd(l, 5, param);
+ r = param_eval_dbl(l, 6, param) + rot;
+ x1 = x - w/2; x2 = x + w/2;
+ y1 = y2 = y;
+ th = h;
+ goto line_xy;
+ case GEMO_SET:
+ n = l->idx;
+ r = param_eval_dbl(l, 1, param);
+ vtd0_set(param, n-1, r);
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Render a macro aperture using a macro def into a polygon */
+static camv_any_obj_t *aper_macro_render(ge_aper_t *aper, double rot)
+{
+ pcb_polyarea_t *pa;
+ const ge_aper_macro_t *am = aper->data.macro.am;
+ const ge_macro_line_t *l;
+ vtd0_t param;
+
+ /* need a copy of the parameters because they may change ($n=... in macro) */
+ vtd0_init(¶m);
+ vtd0_copy(¶m, 0, &aper->data.macro.param, 0, aper->data.macro.param.used);
+
+ pa = NULL;
+ for(l = am->line1; l != NULL; l = l->next)
+ macro_line_render(&pa, l, ¶m, rot);
+
+ if (pa == NULL) {
+ pcb_message(PCB_MSG_WARNING, "aperture macro results in empty render\n");
+ return NULL;
+ }
+ return polyarea2camv(pa);
+}
+
+
+static camv_any_obj_t *gedraw_render_aper_nohole(camv_design_t *camv, ge_aper_t *aper, pcb_coord_t ox, pcb_coord_t oy, double rot)
+{
+ camv_any_obj_t *o;
+ double rx, ry;
+ int n;
+
+ switch(aper->shape) {
+ case GEA_CIRC:
+ o = (camv_any_obj_t *)camv_line_new();
+ o->line.x1 = o->line.x2 = ox;
+ o->line.y1 = o->line.y2 = oy;
+ o->line.thick = aper->data.circ.dia;
+ return o;
+
+ case GEA_RECT:
+ o = (camv_any_obj_t *)camv_poly_new();
+ camv_poly_allocpts(&o->poly, 4);
+
+ rx = ((double)aper->data.rect.xs / 2.0);
+ ry = ((double)aper->data.rect.ys / 2.0);
+
+ o->poly.x[3] = pcb_round((double)ox - rx);
+ o->poly.y[3] = pcb_round((double)oy - ry);
+ o->poly.x[2] = pcb_round((double)ox + rx);
+ o->poly.y[2] = pcb_round((double)oy - ry);
+ o->poly.x[1] = pcb_round((double)ox + rx);
+ o->poly.y[1] = pcb_round((double)oy + ry);
+ o->poly.x[0] = pcb_round((double)ox - rx);
+ o->poly.y[0] = pcb_round((double)oy + ry);
+ if (rot != 0) {
+ rot = rot / PCB_RAD_TO_DEG;
+ for(n = 0; n < 4; n++)
+ pcb_rotate(&o->poly.x[n], &o->poly.y[n], ox, oy, cos(rot), sin(rot));
+ }
+
+ return o;
+
+ case GEA_OBLONG:
+ if (aper->cached == NULL)
+ aper->cached = aper_oblong2poly(aper, rot);
+ o = camv_obj_dup(aper->cached);
+ o->proto.calls->move(o, ox, oy);
+ return o;
+
+ case GEA_POLY:
+ if (aper->cached == NULL)
+ aper->cached = aper_poly2poly_nohole(aper, rot);
+ o = camv_obj_dup(aper->cached);
+ o->proto.calls->move(o, ox, oy);
+ return o;
+
+ case GEA_MACRO:
+ if (aper->cached == NULL)
+ aper->cached = aper_macro_render(aper, rot);
+ if (aper->cached == NULL) /* aperture creation may fail on empty aper */
+ return NULL;
+ o = camv_obj_dup(aper->cached);
+ o->proto.calls->move(o, ox, oy);
+ return o;
+ }
+ return NULL;
+}
+
+static camv_any_obj_t *gedraw_render_aper_hole(camv_design_t *camv, ge_aper_t *aper, pcb_coord_t ox, pcb_coord_t oy, double rot)
+{
+ camv_any_obj_t *o;
+ pcb_polyarea_t *pdiff, *ps, *ph;
+ double rx, ry;
+
+TODO("Generate and cache these and dup with offset instead of reconstructing all the time");
+ switch(aper->shape) {
+ case GEA_CIRC:
+ if (aper->cached == NULL) {
+ ps = pcb_poly_from_circle(0, 0, aper->data.circ.dia/2);
+ ph = pcb_poly_from_circle(0, 0, aper->hole/2);
+ pcb_polyarea_boolean_free(ps, ph, &pdiff, PCB_PBO_SUB);
+ aper->cached = polyarea2camv(pdiff);
+ }
+ o = camv_obj_dup(aper->cached);
+ o->proto.calls->move(o, ox, oy);
+ return o;
+
+
+ case GEA_RECT:
+ if (aper->cached == NULL) {
+ rx = ((double)aper->data.rect.xs / 2.0);
+ ry = ((double)aper->data.rect.ys / 2.0);
+ ps = pcb_poly_from_rect(-rx, +rx, -ry, +ry);
+ ph = pcb_poly_from_circle(0, 0, aper->hole/2);
+ pcb_polyarea_boolean_free(ps, ph, &pdiff, PCB_PBO_SUB);
+ aper->cached = polyarea2camv(pdiff);
+ }
+ o = camv_obj_dup(aper->cached);
+ o->proto.calls->move(o, ox, oy);
+ return o;
+
+ case GEA_OBLONG:
+ if (aper->cached == NULL)
+ aper->cached = aper_oblong2poly(aper, rot); /* handles the hole */
+ o = camv_obj_dup(aper->cached);
+ o->proto.calls->move(o, ox, oy);
+ return o;
+
+ case GEA_POLY:
+ if (aper->cached == NULL)
+ aper->cached = aper_poly2poly_hole(aper, rot);
+ o = camv_obj_dup(aper->cached);
+ o->proto.calls->move(o, ox, oy);
+ return o;
+
+ case GEA_MACRO:
+ return gedraw_render_aper_nohole(camv, aper, ox, oy, rot);
+ }
+
+ return NULL;
+}
+
+/* render an aperture at x;y into a camv drawing primitive (may be a grp).
+ Rot is in deg in gerb notation; x;y are in gerber notation. */
+static camv_any_obj_t *gedraw_render_aper(camv_design_t *camv, ge_aper_t *aper, pcb_coord_t ox, pcb_coord_t oy, double rot)
+{
+ if (aper->hole == 0)
+ return gedraw_render_aper_nohole(camv, aper, ox, oy, rot);
+ else
+ return gedraw_render_aper_hole(camv, aper, ox, oy, rot);
+}
+
+
+/*** gerber state machine ***/
+
+static int gedraw_aper_store(gedraw_ctx_t *ctx, long aid, const ge_aper_t *aper)
+{
+ if (!ctx->aper_inited) {
+ htip_init(&ctx->aper, longhash, longkeyeq);
+ ctx->aper_inited = 1;
+ }
+
+ if (htip_has(&ctx->aper, aid)) {
+ pcb_message(PCB_MSG_ERROR, "gedraw_aper_store: aperture %ld is defuned multiple times\n", aid);
+ return -1;
+ }
+ htip_set(&ctx->aper, aid, (ge_aper_t *)aper); /* can remember by pointer because it's coming from the VM code */
+ return 0;
+}
+
+static ge_aper_t *gedraw_aper_get(gedraw_ctx_t *ctx, long aid)
+{
+ if (!ctx->aper_inited)
+ return NULL;
+ return htip_get(&ctx->aper, aid);
+}
+
+typedef struct {
+ pcb_coord_t x, y, i, j;
+ gedraw_cmd_t op;
+ long aper;
+ ge_interp_t interp;
+ ge_quadr_t quadr;
+ unsigned relcrd:1;
+ unsigned relat:1;
+ unsigned poly:1;
+ unsigned clearing:1;
+} gerbst_t;
+
+
+static void gedraw_poly_close(camv_design_t *camv, gedraw_ctx_t *ctx, camv_layer_t *ly)
+{
+ pcb_cardinal_t n, i;
+ camv_any_obj_t *o;
+
+ if (ctx->contour.used == 0)
+ return;
+ if (ctx->contour.used < 6) {
+ pcb_message(PCB_MSG_ERROR, "gedraw_poly_close: contour with too few vertices (%d)\n", ctx->contour.used/2);
+ ctx->contour.used = 0;
+ return 0;
+ }
+ if (!ctx->poly_closed)
+ pcb_message(PCB_MSG_ERROR, "gedraw_poly_close: contour is not closed\n");
+
+ o = (camv_any_obj_t *)camv_poly_new();
+ camv_poly_allocpts(&o->poly, ctx->contour.used/2);
+ for(n = 0, i = 0; i < ctx->contour.used; n++) {
+ o->poly.x[n] = ctx->contour.array[i++];
+ o->poly.y[n] = ctx->contour.array[i++];
+ }
+ camv_obj_add_to_layer(ly, o);
+ ctx->contour.used = 0;
+ ctx->poly_closed = 0;
+}
+
+static void gedraw_poly_append(gedraw_ctx_t *ctx, pcb_coord_t x, pcb_coord_t y)
+{
+ if ((ctx->contour.used > 5) && (ctx->contour.array[0] == x) && (ctx->contour.array[1] == y)) {
+ /* arrived back at the start, close and avoid dupliocate */
+ ctx->poly_closed = 1;
+ return;
+ }
+
+ if ((ctx->contour.used > 1) && (ctx->contour.array[ctx->contour.used-2] == x) && (ctx->contour.array[ctx->contour.used-1] == y)) {
+ /* new point is the same as last: skip */
+ return;
+ }
+
+ ctx->poly_closed = 0;
+ vtc0_append(&ctx->contour, x);
+ vtc0_append(&ctx->contour, y);
+}
+
+#define SETCRD(dst, src) \
+ do { \
+ if (curr->relcrd) (dst) += (src); \
+ else (dst) = (src); \
+ } while(0)
+
+static void gedraw_do_pol_(camv_design_t *camv, const camv_layer_t *main_layer, camv_layer_t **ly, int clearing)
+{
+ *ly = camv_layer_new();
+ (*ly)->sub = 1;
+ (*ly)->clearing = clearing;
+ (*ly)->color = main_layer->color;
+ camv_layer_append_to_design(camv, *ly);
+}
+
+static void gedraw_do_pol(camv_design_t *camv, const camv_layer_t *main_layer, camv_layer_t **ly, gerbst_t *curr, gerbst_t *last)
+{
+ if (curr->clearing == last->clearing)
+ return; /* optimization: do not create a new layer with the same polarity */
+ gedraw_do_pol_(camv, main_layer, ly, curr->clearing);
+}
+
+static pcb_polyarea_t *pa_rect_side(gerbst_t *c1, gerbst_t *c2, double dx1, double dy1, double dx2, double dy2)
+{
+ pcb_vector_t v;
+ pcb_pline_t *pl;
+
+ v[0] = pcb_round((double)c1->x+dx1);
+ v[1] = pcb_round((double)c1->y+dy1);
+ pl = pcb_poly_contour_new(v);
+
+ v[0] = pcb_round((double)c2->x+dx1);
+ v[1] = pcb_round((double)c2->y+dy1);
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ v[0] = pcb_round((double)c2->x+dx2);
+ v[1] = pcb_round((double)c2->y+dy2);
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ v[0] = pcb_round((double)c1->x+dx2);
+ v[1] = pcb_round((double)c1->y+dy2);
+ pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v));
+
+ return pcb_poly_from_contour_autoinv(pl);
+}
+
+static void gedraw_do_draw_line(camv_design_t *camv, gedraw_ctx_t *ctx, camv_layer_t *ly, gerbst_t *curr, gerbst_t *last)
+{
+ camv_any_obj_t *o;
+ ge_aper_t *aper = gedraw_aper_get(ctx, curr->aper);
+ pcb_polyarea_t *slice, *sum, *pres;
+ double rx, ry;
+
+ if (curr->poly) {
+ gedraw_poly_append(ctx, ctx->ox + last->x, ctx->oy + last->y);
+ gedraw_poly_append(ctx, ctx->ox + curr->x, ctx->oy + curr->y);
+ return;
+ }
+
+ switch(aper->shape) {
+ case GEA_CIRC:
+ o = camv_line_new();
+ o->line.x1 = ctx->ox + last->x; o->line.y1 = ctx->oy + last->y;
+ o->line.x2 = ctx->ox + curr->x; o->line.y2 = ctx->oy + curr->y;
+ o->line.thick = aper->data.circ.dia;
+ camv_obj_add_to_layer(ly, o);
+ break;
+ case GEA_RECT:
+ rx = ((double)aper->data.rect.xs / 2.0);
+ ry = ((double)aper->data.rect.ys / 2.0);
+
+ if ((last->x == curr->x) || (last->y == curr->y)) { /* cheap corner case: axis aligned line or zero length line */
+ double x1, y1, x2, y2;
+
+ x1 = MIN(last->x, curr->x);
+ x2 = MAX(last->x, curr->x);
+ y1 = MIN(last->y, curr->y);
+ y2 = MAX(last->y, curr->y);
+
+ o = (camv_any_obj_t *)camv_poly_new();
+ camv_poly_allocpts(&o->poly, 4);
+ o->poly.x[0] = pcb_round(ctx->ox + x1 - rx);
+ o->poly.y[0] = pcb_round(ctx->oy + y1 - ry);
+ o->poly.x[1] = pcb_round(ctx->ox + x2 + rx);
+ o->poly.y[1] = pcb_round(ctx->oy + y1 - ry);
+ o->poly.x[2] = pcb_round(ctx->ox + x2 + rx);
+ o->poly.y[2] = pcb_round(ctx->oy + y2 + ry);
+ o->poly.x[3] = pcb_round(ctx->ox + x1 - rx);
+ o->poly.y[3] = pcb_round(ctx->oy + y2 + ry);
+ camv_obj_add_to_layer(ly, o);
+ }
+ else {
+ sum = pcb_poly_from_rect(ctx->ox + last->x-rx, ctx->ox + last->x+rx, ctx->oy + last->y-ry, ctx->oy + last->y+ry);
+ slice = pcb_poly_from_rect(ctx->ox + curr->x-rx, ctx->ox + curr->x+rx, ctx->oy + curr->y-ry, ctx->oy + curr->y+ry);
+ pcb_polyarea_boolean_free(sum, slice, &pres, PCB_PBO_UNITE); sum = pres;
+
+ slice = pa_rect_side(last, curr, ctx->ox-rx, ctx->oy-ry, ctx->ox+rx, ctx->oy-ry); /* top horiz */
+ pcb_polyarea_boolean_free(sum, slice, &pres, PCB_PBO_UNITE); sum = pres;
+
+ slice = pa_rect_side(last, curr, ctx->ox+rx, ctx->oy-ry, ctx->ox+rx, ctx->oy+ry); /* right vert */
+ pcb_polyarea_boolean_free(sum, slice, &pres, PCB_PBO_UNITE); sum = pres;
+
+ slice = pa_rect_side(last, curr, ctx->ox-rx, ctx->oy+ry, ctx->ox+rx, ctx->oy+ry); /* bottom horiz */
+ pcb_polyarea_boolean_free(sum, slice, &pres, PCB_PBO_UNITE); sum = pres;
+
+ slice = pa_rect_side(last, curr, ctx->ox-rx, ctx->oy-ry, ctx->ox-rx, ctx->oy+ry); /* left vert */
+ pcb_polyarea_boolean_free(sum, slice, &pres, PCB_PBO_UNITE); sum = pres;
+
+ o = polyarea2camv(sum);
+ camv_obj_add_to_layer(ly, o);
+ }
+ break;
+ default:
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: DRAW line: linear interpolation is permitted only using round or rectangle apertures\n");
+ }
+
+}
+
+static void gedraw_do_draw_arc(camv_design_t *camv, gedraw_ctx_t *ctx, camv_layer_t *ly, gerbst_t *curr, gerbst_t *last, int is_cw)
+{
+ camv_arc_t *arc;
+ ge_aper_t *aper = gedraw_aper_get(ctx, curr->aper);
+ pcb_coord_t cx, cy, r1, r2;
+ double ang1, ang2, delta;
+
+ if (aper->shape != GEA_CIRC) {
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: DRAW arc: circular interpolation is permitted only with fileld circle aperture\n");
+ return;
+ }
+
+ if (curr->quadr == GEQ_SINGLE) {
+ pcb_coord_t i = curr->i, j = curr->j;
+ /* it seems I;J sign is ignored and reconstructed from last->curr movement */
+ if (i < 0) {
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: DRAW arc: single quadrant I should be positive\n");
+ i = -i;
+ }
+ if (j < 0) {
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: DRAW arc: single quadrant J should be positive\n");
+ j = -j;
+ }
+ if (curr->x < last->x) i = -i;
+ if (curr->y < last->y) j = -j;
+ cx = last->x + i;
+ cy = last->y + j;
+ }
+ else {
+ /* in multi-quadrant mode I and J are just signed */
+ cx = last->x + curr->i;
+ cy = last->y + curr->j;
+ }
+
+ ang1 = atan2(last->y - cy, last->x - cx) * PCB_RAD_TO_DEG;
+ ang2 = atan2(curr->y - cy, curr->x - cx) * PCB_RAD_TO_DEG;
+
+ if (ang1 < 0) ang1 += 360;
+ if (ang2 < 0) ang2 += 360;
+
+ if (curr->quadr == GEQ_SINGLE) {
+ if (is_cw) {
+ delta = ang2 - ang1;
+ if (delta > 90)
+ delta -= 360;
+ if ((delta < 0.0) || (delta > 90.0))
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: DRAW arc: single quadrant arc with angle span out of range (CW)\n");
+ }
+ else {
+ delta = ang1 - ang2;
+ if (delta < -90)
+ delta += 360;
+ if ((delta < -90.0) || (delta > 0.0))
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: DRAW arc: single quadrant arc with angle span out of range (CCW)\n");
+ delta = -delta;
+ }
+ }
+ else {
+ if (is_cw) { /* CW */
+ delta = ang1 - ang2;
+ if (delta < 0) {
+ delta = 360 + delta;
+ }
+ delta = -delta;
+ }
+ else { /* CCW */
+ delta = ang2 - ang1;
+ if (delta < 0)
+ delta = 360 + delta;
+ }
+ }
+
+ r1 = pcb_distance(last->x, last->y, cx, cy);
+ r2 = pcb_distance(curr->x, curr->y, cx, cy);
+ if (fabs(r1 - r2) > 2*ctx->acceptable_error)
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: DRAW arc: not circular: radius %.6mm vs. %.6mm\n", (pcb_coord_t)pcb_round(r1), (pcb_coord_t)pcb_round(r2));
+
+ if (curr->poly) {
+ double a, a1, a2, dlt, step;
+
+ if (delta == 0) /* zero length arc means no modification to a poly contour */
+ return;
+
+ if ((delta < 0) && (ang2 > ang1)) ang2 -= 360;
+ if ((delta > 0) && (ang1 > ang2)) ang1 -= 360;
+
+ dlt = delta / PCB_RAD_TO_DEG;
+ a1 = ang1 / PCB_RAD_TO_DEG;
+ a2 = ang2 / PCB_RAD_TO_DEG;
+ step = (PCB_COORD_TO_MM(r1)*8.0);
+ if (step < 4)
+ step = 4;
+ step = dlt / step;
+ for(a = a1; (step < 0) ? (a > a2) : (a < a2); a += step)
+ gedraw_poly_append(ctx, pcb_round(ctx->ox + cx + cos(a) * r1), pcb_round(ctx->oy + cy + sin(a) * r1));
+
+ gedraw_poly_append(ctx, ctx->ox + curr->x, ctx->oy + curr->y); /* make sure we arrive at the endpoint requested */
+ return;
+ }
+
+ arc = camv_arc_new();
+ arc->cx = ctx->ox + cx; arc->cy = ctx->oy + cy; arc->r = r1;
+ arc->thick = aper->data.circ.dia;
+ arc->start = 180 - ang1;
+ arc->delta = -delta;
+ camv_obj_add_to_layer(ly, (camv_any_obj_t *)arc);
+}
+
+static void gedraw_do_draw(camv_design_t *camv, gedraw_ctx_t *ctx, camv_layer_t *ly, gerbst_t *curr, gerbst_t *last)
+{
+ switch(curr->interp) {
+ case GEI_LIN: gedraw_do_draw_line(camv, ctx, ly, curr, last); break;
+ case GEI_CW: gedraw_do_draw_arc(camv, ctx, ly, curr, last, 1); break;
+ case GEI_CCW: gedraw_do_draw_arc(camv, ctx, ly, curr, last, 0); break;
+ }
+}
+
+static void gedraw_do_move(camv_design_t *camv, gedraw_ctx_t *ctx, camv_layer_t *ly, gerbst_t *curr, gerbst_t *last)
+{
+ /* auto-close poly contour on _real_ move; a move that stats in place is not
+ really a move and shouldn't break the contour - this is how the reference
+ viewer v2018.11b works */
+ if ((curr->poly) && ((curr->x != last->x) || (curr->y != last->y))) {
+ gedraw_poly_close(camv, ctx, ly);
+ return;
+ }
+ /* normal draw: do nothing, coords are getting updated on the curr-to-last copy */
+}
+
+static void gedraw_do_flash(camv_design_t *camv, gedraw_ctx_t *ctx, camv_layer_t *ly, gerbst_t *curr, gerbst_t *last)
+{
+ camv_any_obj_t *o;
+ ge_aper_t *aper = gedraw_aper_get(ctx, curr->aper);
+
+ if (aper == NULL)
+ return;
+ o = gedraw_render_aper(camv, aper, curr->x + ctx->ox, curr->y + ctx->oy, 0);
+ if (o != NULL)
+ camv_obj_add_to_layer(ly, o);
+ else
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: failed to FLASH aperture %ld\n", curr->aper);
+}
+
+static void gedraw_do(camv_design_t *camv, gedraw_ctx_t *ctx, const camv_layer_t *main_layer, camv_layer_t **ly, gerbst_t *curr, gerbst_t *last)
+{
+ switch(curr->op) {
+ case GEC_SET_POLCLR: gedraw_do_pol(camv, main_layer, ly, curr, last); break;
+ case GEC_DRAW: gedraw_do_draw(camv, ctx, *ly, curr, last); break;
+ case GEC_MOVE: gedraw_do_move(camv, ctx, *ly, curr, last); break;
+ case GEC_FLASH: gedraw_do_flash(camv, ctx, *ly, curr, last); break;
+
+ case GEC_invalid:
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: invalid opcode %d (uninitialized) \n", curr->op);
+ break;
+ default:
+ pcb_message(PCB_MSG_ERROR, "gedraw_do: invalid opcode %d (unrecognized)\n", curr->op);
+ }
+ memcpy(last, curr, sizeof(gerbst_t));
+}
+
+static int gedraw_camv_(camv_design_t *camv, gedraw_ctx_t *ctx, const camv_layer_t *main_layer, camv_layer_t **layer, size_t *from, int in_sr, gerbst_t *curr, gerbst_t *last)
+{
+ size_t n;
+ camv_layer_t *ly = *layer;
+
+ for(n = *from; n < ctx->code.used; n++) {
+ gedraw_inst_t *i = &ctx->code.array[n]; /* need to retrieve it each iteration because n may jump after SR */
+ switch(i->cmd) {
+ case GEC_SET_X: SETCRD(curr->x, i->data.coord); break;
+ case GEC_SET_Y: SETCRD(curr->y, i->data.coord); break;
+ case GEC_SET_I: SETCRD(curr->i, i->data.coord); break;
+ case GEC_SET_J: SETCRD(curr->j, i->data.coord); break;
+ case GEC_SET_RELAT: curr->relat = i->data.on; break;
+ case GEC_SET_RELCRD: curr->relcrd = i->data.on; break;
+ case GEC_SET_INTERP: curr->interp = i->data.interp; break;
+ case GEC_SET_QUADR: curr->quadr = i->data.quadr; break;
+
+ case GEC_SET_POLY:
+ if ((curr->poly) && (!i->data.on))
+ gedraw_poly_close(camv, ctx, ly);
+ curr->poly = i->data.on;
+ break;
+
+ case GEC_APER_DEF:
+ if (gedraw_aper_store(ctx, i->data.aper.id, &i->data.aper) != 0)
+ return -1;
+ break;
+
+ case GEC_APER_SEL:
+ curr->aper = i->data.id;
+ if (gedraw_aper_get(ctx, curr->aper) == NULL) {
+ pcb_message(PCB_MSG_ERROR, "gedraw_camv: selected invalid (undefined) aperture %ld\n", curr->aper);
+ return -1;
+ }
+ break;
+
+ case GEC_SET_POLCLR: curr->op = i->cmd; curr->clearing = i->data.on; break;
+
+ case GEC_DRAW:
+ case GEC_MOVE:
+ case GEC_FLASH: curr->op = i->cmd; break;
+
+ case GEC_DO: gedraw_do(camv, ctx, main_layer, &ly, curr, last); break;
+
+ case GEC_invalid:
+ pcb_message(PCB_MSG_ERROR, "gedraw_camv: invalid opcode %d (uninitialized) \n", i->cmd);
+ break;
+
+ case GEC_STEPREP:
+ if (!in_sr) {
+ int nx, ny, vx, vy, was_clearing;
+ size_t srn;
+
+ was_clearing = ly->clearing;
+ vx = i->data.steprep.x;
+ vy = i->data.steprep.y;
+ if ((vx <= 1) && (vy <= 1)) {
+ n++;
+ goto quit_sr; /* a new SR terminates an already open one */
+ }
+
+ if (vx < 1) {
+ pcb_message(PCB_MSG_ERROR, "gedraw_camv: invalid SR x\n");
+ return -1;
+ }
+ if (vy < 1) {
+ pcb_message(PCB_MSG_ERROR, "gedraw_camv: invalid SR y\n");
+ return -1;
+ }
+ for(nx = 0; nx < vx; nx++) {
+ for(ny = 0; ny < vy; ny++) {
+ gedraw_ctx_t srctx;
+ gerbst_t srcurr, srlast;
+
+ memcpy(&srctx, ctx, sizeof(gedraw_ctx_t));
+ memcpy(&srcurr, curr, sizeof(gerbst_t));
+ memcpy(&srlast, last, sizeof(gerbst_t));
+ srctx.ox = ctx->ox + nx * i->data.steprep.i;
+ srctx.oy = ctx->oy + ny * i->data.steprep.j;
+ srn = n+1;
+ if (gedraw_camv_(camv, &srctx, main_layer, &ly, &srn, 1, &srcurr, &srlast) != 0)
+ return -1;
+ if (was_clearing != ly->clearing) {
+ /* if last layer doesn't match initial polarity, the only way to restore the original polarity is to create a new sublayer */
+ gedraw_do_pol_(camv, main_layer, &ly, was_clearing);
+ }
+ }
+ }
+ n = srn-1; /* continue with the next instruction after the block */
+ }
+ else {
+ if ((i->data.steprep.x <= 1) && (i->data.steprep.y <= 1))
+ n++; /* closing SR, won't start a loop, skip it */
+ goto quit_sr; /* a new SR terminates an already open one */
+ }
+ }
+ }
+
+ quit_sr:;
+ *layer = ly;
+ *from = n;
+ return 0;
+}
+
+static int gedraw_camv(camv_design_t *camv, gedraw_ctx_t *ctx, const char *name)
+{
+ size_t from = 0;
+ camv_layer_t *ly = camv_layer_new();
+ ly->name = pcb_strdup(name);
+ camv_layer_invent_color(camv, ly); /* gerber files do not have layer color */
+ camv_layer_append_to_design(camv, ly);
+ gerbst_t curr, last;
+
+ memset(&curr, 0, sizeof(curr));
+ curr.interp = GEI_LIN;
+ curr.quadr = GEQ_INVALID;
+ memcpy(&last, &curr, sizeof(last));
+
+ return gedraw_camv_(camv, ctx, ly, &ly, &from, 0, &curr, &last);
+}
+
+static int ge_getchar(geparse_ctx_t *ctx)
+{
+ return fgetc((FILE *)ctx->user_data);
+}
+
+int camv_gerb_load(camv_design_t *camv, const char *fn, FILE *f)
+{
+ geparse_ctx_t ctx;
+ ge_parse_res_t res;
+ int retv;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.getchar = ge_getchar;
+ ctx.user_data = f;
+ while((res = geparse(&ctx)) == GEP_NEXT) ;
+ if (res == GEP_ERROR) {
+ pcb_message(PCB_MSG_ERROR, "parse error at %ld:%ld: %s\n", ctx.line, ctx.col, ctx.errmsg);
+ return -1;
+ }
+
+ if (ctx.unit == GEU_INCH)
+ ctx.draw.acceptable_error = PCB_INCH_TO_COORD((double)pow(0.1, ctx.cfmt_fra));
+ else
+ ctx.draw.acceptable_error = PCB_MM_TO_COORD((double)pow(0.1, ctx.cfmt_fra));
+
+ retv = gedraw_camv(camv, &ctx.draw, fn);
+
+ if (ctx.draw.aper_inited) {
+ htip_entry_t *e;
+ for(e = htip_first(&ctx.draw.aper); e != NULL; e = htip_next(&ctx.draw.aper, e)) {
+ ge_aper_t *aper = e->value;
+ if (aper->cached != NULL)
+ camv_obj_free(aper->cached);
+ }
+ htip_uninit(&ctx.draw.aper);
+ }
+
+ geparse_free(&ctx);
+ return retv;
+}
+
+static int camv_gerb_test_load(camv_design_t *camv, const char *fn, FILE *f)
+{
+ char *line, line_[1024];
+ int bad = 0;
+
+ while((line = fgets(line_, sizeof(line_), f)) != NULL) {
+ while(isspace(*line)) line++;
+ if (strncmp(line, "M02*", 4) == 0)
+ return 1;
+ if (strncmp(line, "%MOIN", 5) == 0)
+ return 1;
+ if (strncmp(line, "%MOMM", 5) == 0)
+ return 1;
+ if ((strncmp(line, "%ADD", 4) == 0) && (isdigit(line[4])))
+ return 1;
+ bad++;
+ if (bad > 64)
+ return 0;
+ }
+ return 0;
+}
+
+static camv_io_t io_gerb = {
+ "gerber", 90,
+ camv_gerb_test_load,
+ camv_gerb_load,
+ NULL,
+};
+
+
+void camv_gerb_init(void)
+{
+ camv_io_reg(&io_gerb);
+}
Index: trunk/src/gerb/gex.tab.c
===================================================================
--- trunk/src/gerb/gex.tab.c (nonexistent)
+++ trunk/src/gerb/gex.tab.c (revision 1)
@@ -0,0 +1,585 @@
+/* original parser id follows */
+/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYPATCH 20140715
+
+#define YYEMPTY (-1)
+#define yyclearin (yychar = YYEMPTY)
+#define yyerrok (yyerrflag = 0)
+#define YYRECOVERING() (yyerrflag != 0)
+#define YYENOMEM (-2)
+#define YYEOF 0
+
+#ifndef yyparse
+#define yyparse gexparse
+#endif /* yyparse */
+
+#ifndef yylex
+#define yylex gexlex
+#endif /* yylex */
+
+#ifndef yyerror
+#define yyerror gexerror
+#endif /* yyerror */
+
+#ifndef yychar
+#define yychar gexchar
+#endif /* yychar */
+
+#ifndef yyval
+#define yyval gexval
+#endif /* yyval */
+
+#ifndef yylval
+#define yylval gexlval
+#endif /* yylval */
+
+#ifndef yydebug
+#define yydebug gexdebug
+#endif /* yydebug */
+
+#ifndef yynerrs
+#define yynerrs gexnerrs
+#endif /* yynerrs */
+
+#ifndef yyerrflag
+#define yyerrflag gexerrflag
+#endif /* yyerrflag */
+
+#ifndef yylhs
+#define yylhs gexlhs
+#endif /* yylhs */
+
+#ifndef yylen
+#define yylen gexlen
+#endif /* yylen */
+
+#ifndef yydefred
+#define yydefred gexdefred
+#endif /* yydefred */
+
+#ifndef yydgoto
+#define yydgoto gexdgoto
+#endif /* yydgoto */
+
+#ifndef yysindex
+#define yysindex gexsindex
+#endif /* yysindex */
+
+#ifndef yyrindex
+#define yyrindex gexrindex
+#endif /* yyrindex */
+
+#ifndef yygindex
+#define yygindex gexgindex
+#endif /* yygindex */
+
+#ifndef yytable
+#define yytable gextable
+#endif /* yytable */
+
+#ifndef yycheck
+#define yycheck gexcheck
+#endif /* yycheck */
+
+#ifndef yyname
+#define yyname gexname
+#endif /* yyname */
+
+#ifndef yyrule
+#define yyrule gexrule
+#endif /* yyrule */
+#define YYPREFIX "gex"
+
+#define YYPURE 1
+
+#line 2 "gex.y"
+#include "gexpr.h"
+#include
+#line 9 "gex.y"
+#ifdef YYSTYPE
+#undef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+#endif
+#ifndef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+typedef union {
+ double num;
+ int idx;
+} YYSTYPE;
+#endif /* !YYSTYPE_IS_DECLARED */
+#line 116 "gex.tab.c"
+
+/* compatibility with bison */
+#ifdef YYPARSE_PARAM
+/* compatibility with FreeBSD */
+# ifdef YYPARSE_PARAM_TYPE
+# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
+# else
+# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
+# endif
+#else
+# define YYPARSE_DECL() yyparse(ge_expr_prglist_t * ctx)
+#endif
+
+/* Parameters sent to lex. */
+#ifdef YYLEX_PARAM
+# ifdef YYLEX_PARAM_TYPE
+# define YYLEX_DECL() yylex(YYSTYPE *yylval, YYLEX_PARAM_TYPE YYLEX_PARAM)
+# else
+# define YYLEX_DECL() yylex(YYSTYPE *yylval, void * YYLEX_PARAM)
+# endif
+# define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+# define YYLEX_DECL() yylex(YYSTYPE *yylval, ge_expr_prglist_t * ctx)
+# define YYLEX yylex(&yylval, ctx)
+#endif
+
+/* Parameters sent to yyerror. */
+#ifndef YYERROR_DECL
+#define YYERROR_DECL() yyerror(ge_expr_prglist_t * ctx, const char *s)
+#endif
+#ifndef YYERROR_CALL
+#define YYERROR_CALL(msg) yyerror(ctx, msg)
+#endif
+
+extern int YYPARSE_DECL();
+
+#define T_NUM 257
+#define T_PARAM 258
+#define UMINUS 259
+#define YYERRCODE 256
+typedef short YYINT;
+static const YYINT gexlhs[] = { -1,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0,
+};
+static const YYINT gexlen[] = { 2,
+ 3, 0, 3, 3, 3, 3, 3, 1, 1,
+};
+static const YYINT gexdefred[] = { 0,
+ 8, 9, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 1, 0, 0, 6, 7,
+};
+static const YYINT gexdgoto[] = { 5,
+ 6,
+};
+static const YYINT gexsindex[] = { -40,
+ 0, 0, 0, -40, -36, -40, -39, -40, -40, -40,
+ -40, 0, 0, -46, -46, 0, 0,
+};
+static const YYINT gexrindex[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 10, 0, 0,
+};
+static const YYINT gexgindex[] = { 8,
+ 0,
+};
+#define YYTABLESIZE 218
+static const YYINT gextable[] = { 4,
+ 11, 13, 4, 8, 3, 9, 8, 11, 9, 5,
+ 11, 7, 0, 12, 0, 14, 15, 16, 17, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 4, 0, 4, 0, 0,
+ 5, 0, 5, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 10, 0, 0, 0, 0, 0, 0,
+ 10, 0, 0, 10, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 2,
+};
+static const YYINT gexcheck[] = { 40,
+ 47, 41, 0, 43, 45, 45, 43, 47, 45, 0,
+ 47, 4, -1, 6, -1, 8, 9, 10, 11, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 41, -1, 43, -1, 45, -1, -1,
+ 41, -1, 43, -1, 45, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 120, -1, -1, -1, -1, -1, -1,
+ 120, -1, -1, 120, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 257, 258,
+};
+#define YYFINAL 5
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 259
+#define YYUNDFTOKEN 263
+#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a))
+#if YYDEBUG
+static const char *const gexname[] = {
+
+"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,"'('","')'",0,"'+'",0,"'-'",0,"'/'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'x'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"T_NUM",
+"T_PARAM","UMINUS",0,0,0,"illegal-symbol",
+};
+static const char *const gexrule[] = {
+"$accept : expr",
+"expr : '(' expr ')'",
+"$$1 :",
+"expr : '-' $$1 expr",
+"expr : expr '+' expr",
+"expr : expr '-' expr",
+"expr : expr 'x' expr",
+"expr : expr '/' expr",
+"expr : T_NUM",
+"expr : T_PARAM",
+
+};
+#endif
+
+int yydebug;
+int yynerrs;
+
+/* define the initial stack-sizes */
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH 10000
+#endif
+#endif
+
+#define YYINITSTACKSIZE 200
+
+typedef struct {
+ unsigned stacksize;
+ YYINT *s_base;
+ YYINT *s_mark;
+ YYINT *s_last;
+ YYSTYPE *l_base;
+ YYSTYPE *l_mark;
+} YYSTACKDATA;
+
+#if YYDEBUG
+#include /* needed for printf */
+#endif
+
+#include /* needed for malloc, etc */
+#include /* needed for memset */
+
+/* allocate initial stack or double stack size, up to YYMAXDEPTH */
+static int yygrowstack(YYSTACKDATA *data)
+{
+ int i;
+ unsigned newsize;
+ YYINT *newss;
+ YYSTYPE *newvs;
+
+ if ((newsize = data->stacksize) == 0)
+ newsize = YYINITSTACKSIZE;
+ else if (newsize >= YYMAXDEPTH)
+ return YYENOMEM;
+ else if ((newsize *= 2) > YYMAXDEPTH)
+ newsize = YYMAXDEPTH;
+
+ i = (int) (data->s_mark - data->s_base);
+ newss = (YYINT *)realloc(data->s_base, newsize * sizeof(*newss));
+ if (newss == 0)
+ return YYENOMEM;
+
+ data->s_base = newss;
+ data->s_mark = newss + i;
+
+ newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
+ if (newvs == 0)
+ return YYENOMEM;
+
+ data->l_base = newvs;
+ data->l_mark = newvs + i;
+
+ data->stacksize = newsize;
+ data->s_last = data->s_base + newsize - 1;
+ return 0;
+}
+
+#if YYPURE || defined(YY_NO_LEAKS)
+static void yyfreestack(YYSTACKDATA *data)
+{
+ free(data->s_base);
+ free(data->l_base);
+ memset(data, 0, sizeof(*data));
+}
+#else
+#define yyfreestack(data) /* nothing */
+#endif
+
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+
+int
+YYPARSE_DECL()
+{
+ int yyerrflag;
+ int yychar;
+ YYSTYPE yyval;
+ YYSTYPE yylval;
+
+ /* variables for the parser stack */
+ YYSTACKDATA yystack;
+ int yym, yyn, yystate;
+#if YYDEBUG
+ const char *yys;
+
+ if ((yys = getenv("YYDEBUG")) != 0)
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif
+
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = YYEMPTY;
+ yystate = 0;
+
+#if YYPURE
+ memset(&yystack, 0, sizeof(yystack));
+#endif
+
+ if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystack.s_mark = yystack.s_base;
+ yystack.l_mark = yystack.l_base;
+ yystate = 0;
+ *yystack.s_mark = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+ if (yychar < 0)
+ {
+ if ((yychar = YYLEX) < 0) yychar = YYEOF;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ }
+ if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, shifting to state %d\n",
+ YYPREFIX, yystate, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
+ {
+ goto yyoverflow;
+ }
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+ yychar = YYEMPTY;
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag) goto yyinrecovery;
+
+ YYERROR_CALL("syntax error");
+
+ goto yyerrlab;
+
+yyerrlab:
+ ++yynerrs;
+
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
+ {
+ goto yyoverflow;
+ }
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: error recovery discarding state %d\n",
+ YYPREFIX, *yystack.s_mark);
+#endif
+ if (yystack.s_mark <= yystack.s_base) goto yyabort;
+ --yystack.s_mark;
+ --yystack.l_mark;
+ }
+ }
+ }
+ else
+ {
+ if (yychar == YYEOF) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ yychar = YYEMPTY;
+ goto yyloop;
+ }
+
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+ YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ if (yym)
+ yyval = yystack.l_mark[1-yym];
+ else
+ memset(&yyval, 0, sizeof yyval);
+ switch (yyn)
+ {
+case 2:
+#line 25 "gex.y"
+ { gex_append(ctx, SUB, 0); gex_append(ctx, PUSH_NUM, 0); }
+break;
+case 4:
+#line 27 "gex.y"
+ { gex_append(ctx, ADD, 0); }
+break;
+case 5:
+#line 28 "gex.y"
+ { gex_append(ctx, SUB, 0); }
+break;
+case 6:
+#line 29 "gex.y"
+ { gex_append(ctx, MUL, 0); }
+break;
+case 7:
+#line 30 "gex.y"
+ { gex_append(ctx, DIV, 0); }
+break;
+case 8:
+#line 31 "gex.y"
+ { gex_append(ctx, PUSH_NUM, yystack.l_mark[0].num); }
+break;
+case 9:
+#line 32 "gex.y"
+ { gex_append_idx(ctx, PUSH_PARAM, yystack.l_mark[0].idx); }
+break;
+#line 527 "gex.tab.c"
+ }
+ yystack.s_mark -= yym;
+ yystate = *yystack.s_mark;
+ yystack.l_mark -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yystack.s_mark = YYFINAL;
+ *++yystack.l_mark = yyval;
+ if (yychar < 0)
+ {
+ if ((yychar = YYLEX) < 0) yychar = YYEOF;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == YYEOF) goto yyaccept;
+ goto yyloop;
+ }
+ if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
+ {
+ goto yyoverflow;
+ }
+ *++yystack.s_mark = (YYINT) yystate;
+ *++yystack.l_mark = yyval;
+ goto yyloop;
+
+yyoverflow:
+ YYERROR_CALL("yacc stack overflow");
+
+yyabort:
+ yyfreestack(&yystack);
+ return (1);
+
+yyaccept:
+ yyfreestack(&yystack);
+ return (0);
+}
Index: trunk/src/gerb/gex.tab.h
===================================================================
--- trunk/src/gerb/gex.tab.h (nonexistent)
+++ trunk/src/gerb/gex.tab.h (revision 1)
@@ -0,0 +1,15 @@
+#define T_NUM 257
+#define T_PARAM 258
+#define UMINUS 259
+#ifdef YYSTYPE
+#undef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+#endif
+#ifndef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+typedef union {
+ double num;
+ int idx;
+} YYSTYPE;
+#endif /* !YYSTYPE_IS_DECLARED */
+extern YYSTYPE gexlval;
Index: trunk/src/gerb/gex.y
===================================================================
--- trunk/src/gerb/gex.y (nonexistent)
+++ trunk/src/gerb/gex.y (revision 1)
@@ -0,0 +1,35 @@
+%{
+#include "gexpr.h"
+#include
+%}
+
+%lex-param { ge_expr_prglist_t *ctx }
+%parse-param { ge_expr_prglist_t *ctx }
+
+%union {
+ double num;
+ int idx;
+}
+
+%token T_NUM
+%token T_PARAM
+
+%left '+' '-'
+%left 'x' '/'
+%left UMINUS
+
+%%
+
+expr:
+ '(' expr ')'
+ | '-' { gex_append(ctx, SUB, 0); gex_append(ctx, PUSH_NUM, 0); }
+ expr %prec UMINUS
+ | expr '+' expr { gex_append(ctx, ADD, 0); }
+ | expr '-' expr { gex_append(ctx, SUB, 0); }
+ | expr 'x' expr { gex_append(ctx, MUL, 0); }
+ | expr '/' expr { gex_append(ctx, DIV, 0); }
+ | T_NUM { gex_append(ctx, PUSH_NUM, $1); }
+ | T_PARAM { gex_append_idx(ctx, PUSH_PARAM, $1); }
+ ;
+
+%%
Index: trunk/src/gerb/gexpr.c
===================================================================
--- trunk/src/gerb/gexpr.c (nonexistent)
+++ trunk/src/gerb/gexpr.c (revision 1)
@@ -0,0 +1,153 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer - low level gerber parser
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include "gexpr.h"
+
+#define STACK_MAX 128
+
+#define PUSH(num, is_prm) \
+do { \
+ if (sp == sizeof(stack)) \
+ return GEEE_STACK_OVERFLOW; \
+ stack[sp] = (num); \
+ is_param[sp] = is_prm; \
+ sp++; \
+} while(0)
+
+#define POP_(res) \
+do { \
+ if (sp == 0) \
+ return GEEE_STACK_UNDERFLOW; \
+ sp--; \
+ res = stack[sp]; \
+} while(0)
+
+#define POP(res) \
+do { \
+ if (sp == 0) \
+ return GEEE_STACK_UNDERFLOW; \
+ sp--; \
+ res = stack[sp]; \
+ if (is_param[sp]) { \
+ double *__d__; \
+ __d__ = vtd0_get(params, res-1, 0); \
+ if (__d__ == NULL) \
+ res = 0; \
+ else \
+ res = *__d__; \
+ } \
+} while(0)
+
+#define POP_REQ(res, req_prm) \
+do { \
+ POP_(res); \
+ if (is_param[sp] != req_prm) \
+ return GEEE_INTERNAL; \
+} while(0)
+
+ge_expr_err_t gex_eval(ge_expr_prg_t *prg, vtd0_t *params, double *res)
+{
+ char is_param[STACK_MAX];
+ double stack[STACK_MAX];
+ double o1, o2;
+ int sp = 0; /* next stack item to use, length of the stack */
+ double *d;
+
+ for(;prg != NULL; prg = prg->next) {
+ switch(prg->inst) {
+ case PUSH_NUM:
+ PUSH(prg->payload, 0);
+ break;
+ case PUSH_PARAM:
+ PUSH(prg->payload, 1);
+ break;
+ case SET:
+ d = vtd0_get(params, prg->payload-1, 1);
+ POP_REQ(*d, 0);
+ break;
+ case ADD:
+ POP(o1); POP(o2);
+ PUSH(o2+o1, 0);
+ break;
+ case SUB:
+ POP(o1); POP(o2);
+ PUSH(o2-o1, 0);
+ break;
+ case MUL:
+ POP(o1); POP(o2);
+ PUSH(o2*o1, 0);
+ break;
+ case DIV:
+ POP(o1); POP(o2);
+ if (o1 == 0)
+ return GEEE_DIV0;
+ PUSH(o2/o1, 0);
+ break;
+ }
+ }
+ POP(o1);
+ *res = o1;
+ return GEEE_SUCCESS;
+}
+
+static ge_expr_prg_t *gex_append_(ge_expr_prglist_t *ctx)
+{
+ ge_expr_prg_t *ex = malloc(sizeof(ge_expr_prg_t));
+ if (ctx->last != NULL) {
+ ctx->last->next = ex;
+ ctx->last = ex;
+ }
+ else
+ ctx->first = ctx->last = ex;
+
+ ex->next = NULL;
+ return ex;
+}
+
+void gex_append(ge_expr_prglist_t *ctx, gexi_t inst, double payload)
+{
+ ge_expr_prg_t *ex = gex_append_(ctx);
+ ex->inst = inst;
+ ex->payload = payload;
+}
+
+void gex_append_idx(ge_expr_prglist_t *ctx, gexi_t inst, int payload)
+{
+ ge_expr_prg_t *ex = gex_append_(ctx);
+ ex->inst = inst;
+ ex->payload = payload;
+}
+
+void gex_free_prg(ge_expr_prg_t *prg)
+{
+ ge_expr_prg_t *next;
+ for(; prg != NULL; prg = next) {
+ next = prg->next;
+ free(prg);
+ }
+}
Index: trunk/src/gerb/gexpr.h
===================================================================
--- trunk/src/gerb/gexpr.h (nonexistent)
+++ trunk/src/gerb/gexpr.h (revision 1)
@@ -0,0 +1,53 @@
+#ifndef CAMV_GEX_H
+#define CAMV_GEX_H
+
+#include
+
+#include "gex.tab.h"
+
+typedef enum {
+ PUSH_NUM, /* payload is the number to push */
+ PUSH_PARAM, /* push a $N parameter supplied by the caller; payload is the parameter idx */
+ SET, /* payload is destination param number, [TOP] is the value */
+
+ /* these remove [TOP] and [TOP-1], and push the result */
+ ADD,
+ SUB,
+ MUL,
+ DIV
+} gexi_t;
+
+typedef struct ge_expr_prg_s ge_expr_prg_t;
+struct ge_expr_prg_s {
+ gexi_t inst;
+ double payload;
+ ge_expr_prg_t *next;
+};
+
+typedef enum {
+ GEEE_SUCCESS = 0,
+ GEEE_STACK_OVERFLOW,
+ GEEE_STACK_UNDERFLOW,
+ GEEE_DIV0,
+ GEEE_INTERNAL
+} ge_expr_err_t;
+
+
+typedef struct ge_expr_prglist_s {
+ ge_expr_prg_t *first;
+ ge_expr_prg_t *last;
+ void *parent;
+} ge_expr_prglist_t;
+
+extern int gexlex(YYSTYPE *dummy, ge_expr_prglist_t *ctx);
+extern int gexerror(ge_expr_prglist_t *ctx, const char *msg);
+
+void gex_append(ge_expr_prglist_t *ctx, gexi_t inst, double payload);
+void gex_append_idx(ge_expr_prglist_t *ctx, gexi_t inst, int payload);
+
+ge_expr_err_t gex_eval(ge_expr_prg_t *prg, vtd0_t *params, double *res);
+
+void gex_free_prg(ge_expr_prg_t *prg);
+
+
+#endif
Index: trunk/src/gerb/poly-brush/doc/cases.lht
===================================================================
--- trunk/src/gerb/poly-brush/doc/cases.lht (nonexistent)
+++ trunk/src/gerb/poly-brush/doc/cases.lht (revision 1)
@@ -0,0 +1,729 @@
+ha:pcb-rnd-board-v6 {
+
+ ha:attributes {
+ {PCB::grid::unit}=mil
+ }
+
+ li:styles {
+ ha:Signal {
+ diameter = 2.0mm
+ text_scale = 0
+ text_thick = 0.0
+ thickness = 1.0mil
+ hole = 31.5mil
+ clearance = 20.0mil
+ }
+ ha:Power {
+ diameter = 2.2mm
+ text_scale = 0
+ text_thick = 0.0
+ thickness = 20.0mil
+ hole = 1.0mm
+ clearance = 20.0mil
+ }
+ ha:Fat {
+ diameter = 137.8mil
+ text_scale = 0
+ text_thick = 0.0
+ thickness = 80.0mil
+ hole = 47.24mil
+ clearance = 25.0mil
+ }
+ ha:Sig-tight {
+ diameter = 64.0mil
+ text_scale = 0
+ text_thick = 0.0
+ thickness = 10.0mil
+ hole = 31.5mil
+ clearance = 12.0mil
+ }
+ }
+
+ ha:meta {
+ ha:size {
+ thermal_scale = 0.500000
+ x = 127.0mm
+ y = 127.0mm
+ }
+ ha:grid {
+ spacing = 25.0mil
+ offs_x = 0.0
+ offs_y = 0.0
+ }
+ }
+
+ ha:data {
+ li:padstack_prototypes {
+ }
+
+ li:objects {
+ }
+ li:layers {
+
+ ha:top-sig {
+ lid=0
+ group=3
+ ha:combining { }
+
+ li:objects {
+ ha:line.185 {
+ x1=430.0mil; y1=325.0mil; x2=810.0mil; y2=235.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.188 {
+ x1=590.0mil; y1=530.0mil; x2=965.0mil; y2=440.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.191 {
+ x1=720.0mil; y1=445.0mil; x2=340.0mil; y2=535.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.799 {
+ x1=875.0mil; y1=3.925in; x2=26.035mm; y2=3.925in; thickness=20.0mil; clearance=40.0mil;
+ }
+ ha:line.802 {
+ x1=26.035mm; y1=3.925in; x2=975.0mil; y2=99.06mm; thickness=20.0mil; clearance=40.0mil;
+ }
+ ha:line.805 {
+ x1=975.0mil; y1=99.06mm; x2=975.0mil; y2=3.95in; thickness=20.0mil; clearance=40.0mil;
+ }
+ ha:line.808 {
+ x1=975.0mil; y1=3.95in; x2=26.035mm; y2=3.925in; thickness=20.0mil; clearance=40.0mil;
+ }
+ ha:polygon.12 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 475.0mil; 26.035mm }
+ { 375.0mil; 850.0mil }
+ { 250.0mil; 26.035mm }
+ { 350.0mil; 1000.0mil }
+ { 275.0mil; 1.175in }
+ { 350.0mil; 27.305mm }
+ { 350.0mil; 31.75mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.21 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 850.0mil; 825.0mil }
+ { 750.0mil; 650.0mil }
+ { 625.0mil; 825.0mil }
+ { 725.0mil; 800.0mil }
+ { 650.0mil; 975.0mil }
+ { 725.0mil; 875.0mil }
+ { 725.0mil; 26.67mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.117 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 1.1in; 1.175in }
+ { 1000.0mil; 1000.0mil }
+ { 875.0mil; 1.175in }
+ { 975.0mil; 29.21mm }
+ { 900.0mil; 33.655mm }
+ { 995.0mil; 33.147mm }
+ { 975.0mil; 1.4in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.162 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 37.465mm; 975.0mil }
+ { 1.375in; 800.0mil }
+ { 31.75mm; 975.0mil }
+ { 1.35in; 950.0mil }
+ { 1.275in; 1.125in }
+ { 1.37in; 28.067mm }
+ { 1.35in; 30.48mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.293 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 450.0mil; 48.895mm }
+ { 525.0mil; 1.725in }
+ { 700.0mil; 46.355mm }
+ { 750.0mil; 54.61mm }
+ { 575.0mil; 53.975mm }
+ { 650.0mil; 51.435mm }
+ { 525.0mil; 2.0in }
+ { 575.0mil; 1.9in }
+ { 475.0mil; 1.975in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.304 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 1.1in; 48.895mm }
+ { 1.175in; 1.725in }
+ { 1.35in; 46.355mm }
+ { 1.4in; 54.61mm }
+ { 1.225in; 53.975mm }
+ { 1.3in; 51.435mm }
+ { 1.175in; 2.0in }
+ { 1.225in; 1.9in }
+ { 1.125in; 1.975in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.811 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 425.0mil; 3.325in }
+ { 500.0mil; 79.375mm }
+ { 675.0mil; 81.915mm }
+ { 650.0mil; 3.375in }
+ { 700.0mil; 86.995mm }
+ { 650.0mil; 86.36mm }
+ { 675.0mil; 88.9mm }
+ { 725.0mil; 90.17mm }
+ { 550.0mil; 89.535mm }
+ { 625.0mil; 86.995mm }
+ { 500.0mil; 86.36mm }
+ { 550.0mil; 3.3in }
+ { 450.0mil; 3.375in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.825 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 450.0mil; 3.925in }
+ { 525.0mil; 3.725in }
+ { 700.0mil; 97.155mm }
+ { 675.0mil; 100.965mm }
+ { 725.0mil; 4.025in }
+ { 675.0mil; 4.0in }
+ { 700.0mil; 104.14mm }
+ { 750.0mil; 4.15in }
+ { 575.0mil; 104.775mm }
+ { 650.0mil; 4.025in }
+ { 525.0mil; 4.0in }
+ { 575.0mil; 99.06mm }
+ { 475.0mil; 100.965mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.839 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 1.125in; 3.925in }
+ { 30.48mm; 3.725in }
+ { 1.375in; 97.155mm }
+ { 1.35in; 100.965mm }
+ { 1.4in; 4.025in }
+ { 1.356in; 4.025in }
+ { 1.375in; 104.14mm }
+ { 36.195mm; 4.15in }
+ { 31.75mm; 104.775mm }
+ { 33.655mm; 4.025in }
+ { 30.48mm; 4.0in }
+ { 30.7848mm; 100.965mm }
+ { 29.21mm; 100.965mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.853 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 450.0mil; 4.65in }
+ { 525.0mil; 113.03mm }
+ { 700.0mil; 115.57mm }
+ { 675.0mil; 4.7in }
+ { 725.0mil; 120.65mm }
+ { 681.0mil; 120.65mm }
+ { 700.0mil; 122.555mm }
+ { 750.0mil; 123.825mm }
+ { 575.0mil; 4.85in }
+ { 650.0mil; 120.65mm }
+ { 525.0mil; 120.015mm }
+ { 537.0mil; 4.7in }
+ { 475.0mil; 4.7in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.867 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 1.1in; 4.65in }
+ { 1.175in; 113.03mm }
+ { 1.35in; 115.57mm }
+ { 33.655mm; 4.7in }
+ { 1.375in; 120.65mm }
+ { 33.8074mm; 120.65mm }
+ { 1.35in; 122.555mm }
+ { 1.4in; 123.825mm }
+ { 1.225in; 4.85in }
+ { 1.3in; 120.65mm }
+ { 1.175in; 120.015mm }
+ { 1.187in; 4.7in }
+ { 1.125in; 4.7in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.1124 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 8.53243mm; 71.912251mm }
+ { 8.395713mm; 66.488532mm }
+ { 13.468546mm; 67.178452mm }
+ { 14.307036mm; 2.7932637in }
+ { 15.960309mm; 71.650671mm }
+ { 14.544911mm; 71.53766mm }
+ { 16.085173mm; 73.654831mm }
+ { 17.738447mm; 74.356605mm }
+ { 13.37924mm; 75.432969mm }
+ { 14.194024mm; 72.364297mm }
+ { 11.01234mm; 72.964911mm }
+ { 11.238363mm; 70.134113mm }
+ { 9.596942mm; 72.851899mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.1138 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 23.840235mm; 65.727496mm }
+ { 23.703519mm; 60.303777mm }
+ { 28.776352mm; 60.993697mm }
+ { 29.614841mm; 64.764143mm }
+ { 31.268115mm; 65.465916mm }
+ { 29.852716mm; 65.352905mm }
+ { 31.392979mm; 67.470077mm }
+ { 33.046253mm; 68.17185mm }
+ { 28.687045mm; 69.248214mm }
+ { 29.50183mm; 66.179542mm }
+ { 26.320146mm; 2.62914in }
+ { 26.546169mm; 63.949359mm }
+ { 24.904747mm; 66.667145mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:text.314 {
+ string={Horizontal:}; x=300.0mil; y=1.55in; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ ha:text.378 {
+ string={Horizontal:}; x=275.0mil; y=2.325in; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ }
+ color = {#8b2323}
+ }
+
+ ha:bottom-sig {
+ lid=1
+ group=10
+ ha:combining { }
+
+ li:objects {
+ ha:line.32 {
+ x1=375.0mil; y1=850.0mil; x2=750.0mil; y2=650.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.35 {
+ x1=250.0mil; y1=26.035mm; x2=625.0mil; y2=825.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.38 {
+ x1=275.0mil; y1=1.175in; x2=650.0mil; y2=975.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.41 {
+ x1=350.0mil; y1=1000.0mil; x2=725.0mil; y2=800.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.44 {
+ x1=350.0mil; y1=31.75mm; x2=725.0mil; y2=26.67mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.47 {
+ x1=350.0mil; y1=27.305mm; x2=725.0mil; y2=875.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.50 {
+ x1=475.0mil; y1=26.035mm; x2=850.0mil; y2=825.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.133 {
+ x1=1000.0mil; y1=1000.0mil; x2=1.375in; y2=800.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.136 {
+ x1=875.0mil; y1=1.175in; x2=31.75mm; y2=975.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.139 {
+ x1=900.0mil; y1=33.655mm; x2=1.275in; y2=1.125in; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.142 {
+ x1=975.0mil; y1=29.21mm; x2=1.35in; y2=950.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.145 {
+ x1=975.0mil; y1=1.4in; x2=1.35in; y2=30.48mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.151 {
+ x1=1.1in; y1=1.175in; x2=37.465mm; y2=975.0mil; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.170 {
+ x1=995.0mil; y1=33.147mm; x2=1.37in; y2=28.067mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.336 {
+ x1=750.0mil; y1=54.61mm; x2=1.4in; y2=54.61mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.339 {
+ x1=525.0mil; y1=1.725in; x2=1.175in; y2=1.725in; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.345 {
+ x1=475.0mil; y1=1.975in; x2=540.0mil; y2=1.975in; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.699 {
+ x1=0.0; y1=2.25in; x2=127.0mm; y2=2.25in; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.881 {
+ x1=475.0mil; y1=100.965mm; x2=575.0mil; y2=100.965mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.884 {
+ x1=725.0mil; y1=4.025in; x2=675.0mil; y2=4.025in; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.887 {
+ x1=525.0mil; y1=113.03mm; x2=1.175in; y2=113.03mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.890 {
+ x1=750.0mil; y1=123.825mm; x2=1.4in; y2=123.825mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1152 {
+ x1=8.395713mm; y1=66.488532mm; x2=23.703519mm; y2=60.303777mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1155 {
+ x1=17.738447mm; y1=74.356605mm; x2=33.046253mm; y2=68.17185mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1158 {
+ x1=9.596942mm; y1=72.851899mm; x2=24.904747mm; y2=66.667145mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1161 {
+ x1=31.268115mm; y1=65.465916mm; x2=15.960309mm; y2=71.650671mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:polygon.176 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 430.0mil; 325.0mil }
+ { 340.0mil; 535.0mil }
+ { 590.0mil; 530.0mil }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.181 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 810.0mil; 235.0mil }
+ { 720.0mil; 445.0mil }
+ { 970.0mil; 440.0mil }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ }
+ color = {#3a5fcd}
+ }
+
+ ha:top-gnd {
+ lid=2
+ group=3
+ ha:combining { }
+
+ li:objects {
+ ha:text.893 {
+ string={step1: rotate}; x=325.0mil; y=3.05in; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ ha:text.894 {
+ string={step2: semi-convex}; x=325.0mil; y=92.075mm; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ ha:text.895 {
+ string={step3: dup and connect}; x=325.0mil; y=107.95mm; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ }
+ color = {#104e8b}
+ }
+
+ ha:bottom-gnd {
+ lid=3
+ group=10
+ ha:combining { }
+
+ li:objects {
+ }
+ color = {#cd3700}
+ }
+
+ ha:int-sig2 {
+ lid=4
+ group=7
+ ha:combining { }
+
+ li:objects {
+ }
+ color = {#548b54}
+ }
+
+ ha:int-sig1 {
+ lid=5
+ group=5
+ ha:combining { }
+
+ li:objects {
+ }
+ color = {#8b7355}
+ }
+
+ ha:outline {
+ lid=6
+ group=9
+ ha:combining { }
+
+ li:objects {
+ }
+ color = {#00868b}
+ }
+
+ ha:bottom-silk {
+ lid=7
+ group=12
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#000000}
+ }
+
+ ha:top-silk {
+ lid=8
+ group=1
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#000000}
+ }
+
+ ha:top-paste {
+ lid=9
+ group=0
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#cd00cd}
+ }
+
+ ha:top-mask {
+ lid=10
+ group=2
+ ha:combining { sub=1; auto=1; }
+
+ li:objects {
+ }
+ color = {#ff0000}
+ }
+
+ ha:bottom-mask {
+ lid=11
+ group=11
+ ha:combining { sub=1; auto=1; }
+
+ li:objects {
+ }
+ color = {#ff0000}
+ }
+
+ ha:bottom-paste {
+ lid=12
+ group=13
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#cd00cd}
+ }
+
+ ha:slot-plated {
+ lid=13
+ group=14
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#8b7355}
+ }
+
+ ha:slot-unplated {
+ lid=14
+ group=15
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#00868b}
+ }
+ }
+ }
+
+ ha:layer_stack {
+ li:groups {
+ ha:0 {
+ name = top_paste
+ ha:type { top=1; paste=1; }
+ li:layers { 9; }
+ }
+ ha:1 {
+ name = top_silk
+ ha:type { silk=1; top=1; }
+ li:layers { 8; }
+ }
+ ha:2 {
+ name = top_mask
+ ha:type { top=1; mask=1; }
+ li:layers { 10; }
+ }
+ ha:3 {
+ name = top_copper
+ ha:type { copper=1; top=1; }
+ li:layers { 0; 2; }
+ }
+ ha:4 {
+ name = grp_4
+ ha:type { substrate=1; intern=1; }
+ li:layers { }
+ }
+ ha:5 {
+ name = Intern
+ ha:type { copper=1; intern=1; }
+ li:layers { 5; }
+ }
+ ha:6 {
+ name = grp_6
+ ha:type { substrate=1; intern=1; }
+ li:layers { }
+ }
+ ha:7 {
+ name = Intern
+ ha:type { copper=1; intern=1; }
+ li:layers { 4; }
+ }
+ ha:8 {
+ name = grp_8
+ ha:type { substrate=1; intern=1; }
+ li:layers { }
+ }
+ ha:9 {
+ name = global_outline
+ ha:type { boundary=1; }
+ li:layers { 6; }
+ purpose = uroute
+ }
+ ha:10 {
+ name = bottom_copper
+ ha:type { bottom=1; copper=1; }
+ li:layers { 1; 3; }
+ }
+ ha:11 {
+ name = bottom_mask
+ ha:type { bottom=1; mask=1; }
+ li:layers { 11; }
+ }
+ ha:12 {
+ name = bottom_silk
+ ha:type { silk=1; bottom=1; }
+ li:layers { 7; }
+ }
+ ha:13 {
+ name = bottom_paste
+ ha:type { bottom=1; paste=1; }
+ li:layers { 12; }
+ }
+ ha:14 {
+ name = pmech
+ ha:type { mech=1; }
+ li:layers { 13; }
+ purpose = proute
+ }
+ ha:15 {
+ name = umech
+ ha:type { mech=1; }
+ li:layers { 14; }
+ purpose = uroute
+ }
+ }
+ }
+}
Index: trunk/src/gerb/poly-brush/doc/final.lht
===================================================================
--- trunk/src/gerb/poly-brush/doc/final.lht (nonexistent)
+++ trunk/src/gerb/poly-brush/doc/final.lht (revision 1)
@@ -0,0 +1,524 @@
+ha:pcb-rnd-board-v6 {
+
+ li:styles {
+ ha:Signal {
+ diameter = 2.0mm
+ text_scale = 0
+ text_thick = 0.0
+ thickness = 10.0mil
+ hole = 31.5mil
+ clearance = 20.0mil
+ }
+ ha:Power {
+ diameter = 2.2mm
+ text_scale = 0
+ text_thick = 0.0
+ thickness = 20.0mil
+ hole = 1.0mm
+ clearance = 20.0mil
+ }
+ ha:Fat {
+ diameter = 137.8mil
+ text_scale = 0
+ text_thick = 0.0
+ thickness = 80.0mil
+ hole = 47.24mil
+ clearance = 25.0mil
+ }
+ ha:Sig-tight {
+ diameter = 64.0mil
+ text_scale = 0
+ text_thick = 0.0
+ thickness = 10.0mil
+ hole = 31.5mil
+ clearance = 12.0mil
+ }
+ }
+
+ ha:meta {
+ ha:size {
+ thermal_scale = 0.500000
+ x = 31.75mm
+ y = 67.31mm
+ }
+ board_name =
+ ha:grid {
+ spacing = 25.0mil
+ offs_x = 0.0
+ offs_y = 0.0
+ }
+ }
+
+ ha:data {
+ li:padstack_prototypes {
+ }
+
+ li:objects {
+ }
+ li:layers {
+
+ ha:top-sig {
+ lid=0
+ group=3
+ ha:combining { }
+
+ li:objects {
+ ha:line.1305 {
+ x1=650.0mil; y1=1.65in; x2=800.0mil; y2=1.65in; thickness=20.0mil; clearance=40.0mil;
+ }
+ ha:line.1308 {
+ x1=800.0mil; y1=1.65in; x2=750.0mil; y2=1.625in; thickness=20.0mil; clearance=40.0mil;
+ }
+ ha:line.1311 {
+ x1=750.0mil; y1=1.625in; x2=750.0mil; y2=42.545mm; thickness=20.0mil; clearance=40.0mil;
+ }
+ ha:line.1314 {
+ x1=750.0mil; y1=42.545mm; x2=800.0mil; y2=1.65in; thickness=20.0mil; clearance=40.0mil;
+ }
+ ha:polygon.1318 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 200.0mil; 26.67mm }
+ { 275.0mil; 850.0mil }
+ { 450.0mil; 950.0mil }
+ { 425.0mil; 1.1in }
+ { 475.0mil; 29.21mm }
+ { 425.0mil; 1.125in }
+ { 450.0mil; 1.225in }
+ { 500.0mil; 1.275in }
+ { 325.0mil; 31.75mm }
+ { 400.0mil; 29.21mm }
+ { 275.0mil; 1.125in }
+ { 325.0mil; 26.035mm }
+ { 225.0mil; 1.1in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.1332 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 225.0mil; 1.65in }
+ { 300.0mil; 36.83mm }
+ { 475.0mil; 1.55in }
+ { 450.0mil; 43.18mm }
+ { 500.0mil; 44.45mm }
+ { 450.0mil; 1.725in }
+ { 475.0mil; 46.355mm }
+ { 525.0mil; 47.625mm }
+ { 350.0mil; 46.99mm }
+ { 425.0mil; 44.45mm }
+ { 300.0mil; 1.725in }
+ { 350.0mil; 1.625in }
+ { 250.0mil; 43.18mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.1346 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 900.0mil; 1.65in }
+ { 975.0mil; 36.83mm }
+ { 29.21mm; 1.55in }
+ { 1.125in; 43.18mm }
+ { 1.175in; 44.45mm }
+ { 1.131in; 44.45mm }
+ { 29.21mm; 46.355mm }
+ { 30.48mm; 47.625mm }
+ { 26.035mm; 46.99mm }
+ { 1.1in; 44.45mm }
+ { 975.0mil; 1.725in }
+ { 987.0mil; 43.18mm }
+ { 925.0mil; 43.18mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.1360 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 225.0mil; 60.325mm }
+ { 300.0mil; 2.175in }
+ { 475.0mil; 57.785mm }
+ { 450.0mil; 2.425in }
+ { 500.0mil; 62.865mm }
+ { 456.0mil; 62.865mm }
+ { 475.0mil; 2.55in }
+ { 525.0mil; 2.6in }
+ { 350.0mil; 65.405mm }
+ { 425.0mil; 62.865mm }
+ { 300.0mil; 2.45in }
+ { 312.0mil; 2.425in }
+ { 250.0mil; 2.425in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.1374 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 875.0mil; 60.325mm }
+ { 950.0mil; 2.175in }
+ { 1.125in; 57.785mm }
+ { 1.1in; 2.425in }
+ { 29.21mm; 62.865mm }
+ { 1.106in; 62.865mm }
+ { 1.125in; 2.55in }
+ { 1.175in; 2.6in }
+ { 1000.0mil; 65.405mm }
+ { 27.305mm; 62.865mm }
+ { 950.0mil; 2.45in }
+ { 962.0mil; 2.425in }
+ { 900.0mil; 2.425in }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.1388 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 2.81743mm; 14.127251mm }
+ { 2.680713mm; 8.703532mm }
+ { 7.753546mm; 9.393452mm }
+ { 8.592036mm; 13.163898mm }
+ { 10.245309mm; 13.865671mm }
+ { 8.829911mm; 13.75266mm }
+ { 10.370173mm; 15.869831mm }
+ { 12.023447mm; 16.571605mm }
+ { 7.66424mm; 17.647969mm }
+ { 8.479024mm; 14.579297mm }
+ { 5.29734mm; 15.179911mm }
+ { 5.523363mm; 12.349113mm }
+ { 3.881942mm; 15.066899mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:polygon.1402 { clearance=40.0mil;
+ li:geometry {
+ ta:contour {
+ { 18.125235mm; 7.942496mm }
+ { 17.988519mm; 2.518777mm }
+ { 23.061352mm; 3.208697mm }
+ { 23.899841mm; 6.979143mm }
+ { 25.553115mm; 7.680916mm }
+ { 24.137716mm; 7.567905mm }
+ { 25.677979mm; 9.685077mm }
+ { 27.331253mm; 10.38685mm }
+ { 22.972045mm; 11.463214mm }
+ { 23.78683mm; 8.394542mm }
+ { 20.605146mm; 8.995156mm }
+ { 20.831169mm; 6.164359mm }
+ { 19.189747mm; 8.882145mm }
+ }
+ }
+
+ ha:flags {
+ clearpoly=1
+ }
+ }
+ ha:text.1317 {
+ string={Horizontal:}; x=50.0mil; y=50.0mil; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ }
+ color = {#8b2323}
+ }
+
+ ha:bottom-sig {
+ lid=1
+ group=10
+ ha:combining { }
+
+ li:objects {
+ ha:line.1416 {
+ x1=250.0mil; y1=43.18mm; x2=350.0mil; y2=43.18mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1419 {
+ x1=500.0mil; y1=44.45mm; x2=450.0mil; y2=44.45mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1422 {
+ x1=300.0mil; y1=2.175in; x2=950.0mil; y2=2.175in; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1425 {
+ x1=525.0mil; y1=2.6in; x2=1.175in; y2=2.6in; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1428 {
+ x1=2.680713mm; y1=8.703532mm; x2=17.988519mm; y2=2.518777mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1431 {
+ x1=12.023447mm; y1=16.571605mm; x2=27.331253mm; y2=10.38685mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1434 {
+ x1=3.881942mm; y1=15.066899mm; x2=19.189747mm; y2=8.882145mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ ha:line.1437 {
+ x1=25.553115mm; y1=7.680916mm; x2=10.245309mm; y2=13.865671mm; thickness=1.0mil; clearance=40.0mil;
+ }
+ }
+ color = {#3a5fcd}
+ }
+
+ ha:top-gnd {
+ lid=2
+ group=3
+ ha:combining { }
+
+ li:objects {
+ ha:text.1440 {
+ string={step1: rotate}; x=100.0mil; y=750.0mil; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ ha:text.1441 {
+ string={step2: semi-convex}; x=100.0mil; y=1.35in; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ ha:text.1442 {
+ string={step3: dup and connect}; x=100.0mil; y=1.975in; scale=100; fid=0;
+ ha:flags {
+ clearline=1
+ }
+ rot = 0.000000
+ }
+ }
+ color = {#104e8b}
+ }
+
+ ha:bottom-gnd {
+ lid=3
+ group=10
+ ha:combining { }
+
+ li:objects {
+ }
+ color = {#cd3700}
+ }
+
+ ha:int-sig2 {
+ lid=4
+ group=7
+ ha:combining { }
+
+ li:objects {
+ }
+ color = {#548b54}
+ }
+
+ ha:int-sig1 {
+ lid=5
+ group=5
+ ha:combining { }
+
+ li:objects {
+ }
+ color = {#8b7355}
+ }
+
+ ha:outline {
+ lid=6
+ group=9
+ ha:combining { }
+
+ li:objects {
+ }
+ color = {#00868b}
+ }
+
+ ha:bottom-silk {
+ lid=7
+ group=12
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#000000}
+ }
+
+ ha:top-silk {
+ lid=8
+ group=1
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#000000}
+ }
+
+ ha:top-paste {
+ lid=9
+ group=0
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#cd00cd}
+ }
+
+ ha:top-mask {
+ lid=10
+ group=2
+ ha:combining { sub=1; auto=1; }
+
+ li:objects {
+ }
+ color = {#ff0000}
+ }
+
+ ha:bottom-mask {
+ lid=11
+ group=11
+ ha:combining { sub=1; auto=1; }
+
+ li:objects {
+ }
+ color = {#ff0000}
+ }
+
+ ha:bottom-paste {
+ lid=12
+ group=13
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#cd00cd}
+ }
+
+ ha:slot-plated {
+ lid=13
+ group=14
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#8b7355}
+ }
+
+ ha:slot-unplated {
+ lid=14
+ group=15
+ ha:combining { auto=1; }
+
+ li:objects {
+ }
+ color = {#00868b}
+ }
+ }
+ }
+
+ ha:layer_stack {
+ li:groups {
+ ha:0 {
+ name = top_paste
+ ha:type { top=1; paste=1; }
+ li:layers { 9; }
+ }
+ ha:1 {
+ name = top_silk
+ ha:type { silk=1; top=1; }
+ li:layers { 8; }
+ }
+ ha:2 {
+ name = top_mask
+ ha:type { top=1; mask=1; }
+ li:layers { 10; }
+ }
+ ha:3 {
+ name = top_copper
+ ha:type { copper=1; top=1; }
+ li:layers { 0; 2; }
+ }
+ ha:4 {
+ name = grp_4
+ ha:type { substrate=1; intern=1; }
+ li:layers { }
+ }
+ ha:5 {
+ name = Intern
+ ha:type { copper=1; intern=1; }
+ li:layers { 5; }
+ }
+ ha:6 {
+ name = grp_6
+ ha:type { substrate=1; intern=1; }
+ li:layers { }
+ }
+ ha:7 {
+ name = Intern
+ ha:type { copper=1; intern=1; }
+ li:layers { 4; }
+ }
+ ha:8 {
+ name = grp_8
+ ha:type { substrate=1; intern=1; }
+ li:layers { }
+ }
+ ha:9 {
+ name = global_outline
+ ha:type { boundary=1; }
+ li:layers { 6; }
+ purpose = uroute
+ }
+ ha:10 {
+ name = bottom_copper
+ ha:type { bottom=1; copper=1; }
+ li:layers { 1; 3; }
+ }
+ ha:11 {
+ name = bottom_mask
+ ha:type { bottom=1; mask=1; }
+ li:layers { 11; }
+ }
+ ha:12 {
+ name = bottom_silk
+ ha:type { silk=1; bottom=1; }
+ li:layers { 7; }
+ }
+ ha:13 {
+ name = bottom_paste
+ ha:type { bottom=1; paste=1; }
+ li:layers { 12; }
+ }
+ ha:14 {
+ name = pmech
+ ha:type { mech=1; }
+ li:layers { 13; }
+ purpose = proute
+ }
+ ha:15 {
+ name = umech
+ ha:type { mech=1; }
+ li:layers { 14; }
+ purpose = uroute
+ }
+ }
+ }
+}
Index: trunk/src/gerb/regression/am1.gbr
===================================================================
--- trunk/src/gerb/regression/am1.gbr (nonexistent)
+++ trunk/src/gerb/regression/am1.gbr (revision 1)
@@ -0,0 +1,13 @@
+G04 C shaped aperture *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%AMDONUT*
+1,1,$1,0.0,0.0*
+1,0,$2,0.2,0.0*
+%
+%ADD11DONUT,0.60X0.40*%
+G54D11*X10000Y00000D03*
+G54D11*X40000Y11000D02*Y02000D01*
+
+M02*
Index: trunk/src/gerb/regression/am2.gbr
===================================================================
--- trunk/src/gerb/regression/am2.gbr (nonexistent)
+++ trunk/src/gerb/regression/am2.gbr (revision 1)
@@ -0,0 +1,55 @@
+G04 all macro aperture primitives *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+
+%AMP1*
+1,1,5,0.0,0.0,0*
+%
+
+%AMP20*
+20,1,0.5,0,0,3,5,45*
+%
+
+
+%AMP21*
+21,1,0.8,0.5,1,2,45*
+%
+
+%AMP4*
+4,1,3,1,1,6,1,8,0,1,1,45*
+%
+
+%AMP5*
+5,1,3,0,0,2,15*
+%
+
+%AMP6*
+6,1,1,4,0.1,0.5,3,0.05,7,45*
+%
+
+
+%AMP7*
+7,1,1,3,2.5,0.1,20*
+%
+
+
+%ADD11P1*%
+%ADD12P20*%
+%ADD13P21*%
+%ADD14P4*%
+%ADD15P5*%
+%ADD16P6*%
+%ADD17P7*%
+
+
+G54D11*X10000Y00000D03*
+G54D12*X20000Y00000D03*
+G54D13*X30000Y00000D03*
+G54D14*X40000Y00000D03*
+G54D15*X50000Y00000D03*
+G54D16*X60000Y00000D03*
+G54D17*X70000Y00000D03*
+
+
+M02*
Index: trunk/src/gerb/regression/am2r.gbr
===================================================================
--- trunk/src/gerb/regression/am2r.gbr (nonexistent)
+++ trunk/src/gerb/regression/am2r.gbr (revision 1)
@@ -0,0 +1,69 @@
+G04 rotated aperture macro primitives with a thin -+ line marking a known point *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+
+%AMP1*
+1,1,0.5,2,3,33*
+20,0,0.1,0,0,2,3,33*
+20,1,0.05,0,0,2,3,33*
+%
+
+%AMP20*
+20,1,0.5,3,5,1,2,45*
+20,0,0.1,0,0,1,2,45*
+20,1,0.05,0,0,1,2,45*
+%
+
+
+%AMP21*
+21,1,0.8,0.5,1,2,45*
+20,0,0.1,0,0,1,2,45*
+20,1,0.05,0,0,1,2,45*
+%
+
+%AMP4*
+4,1,3,1,1,6,1,8,0,1,1,45*
+20,0,0.1,0,0,1,1,45*
+20,1,0.05,0,0,1,1,45*
+%
+
+%AMP5*
+5,1,3,2,3,2,15*
+20,0,0.1,0,0,2,3,15*
+20,1,0.05,0,0,2,3,15*
+%
+
+%AMP6*
+6,2,3,4,0.1,0.5,3,0.05,7,45*
+20,0,0.1,0,0,2,3,45*
+20,1,0.05,0,0,2,3,45*
+%
+
+
+%AMP7*
+7,2,3,3,2.5,0.1,20*
+20,0,0.1,0,0,2,3,20*
+20,1,0.05,0,0,2,3,20*
+%
+
+
+%ADD11P1*%
+%ADD12P20*%
+%ADD13P21*%
+%ADD14P4*%
+%ADD15P5*%
+%ADD16P6*%
+%ADD17P7*%
+
+
+G54D11*X10000Y10000D03*
+G54D12*X20000Y10000D03*
+G54D13*X30000Y10000D03*
+G54D14*X40000Y10000D03*
+G54D15*X50000Y10000D03*
+G54D16*X60000Y10000D03*
+G54D17*X70000Y10000D03*
+
+
+M02*
Index: trunk/src/gerb/regression/am3.gbr
===================================================================
--- trunk/src/gerb/regression/am3.gbr (nonexistent)
+++ trunk/src/gerb/regression/am3.gbr (revision 1)
@@ -0,0 +1,17 @@
+G04 aperture with arithmetics *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%AMFOO*
+1,1,3,0.0,0.0,0*
+0, comment *
+$3=($1-0.05)x1.5*
+1,0,0.1,$3,0.0,0*
+1,0,0.2,$1-1,0.0,0*
+%
+%ADD11FOO,0.50*%
+%ADD12FOO,1.00*%
+G54D11*X10000Y00000D03*
+G54D12*X20000Y00000D03*
+
+M02*
Index: trunk/src/gerb/regression/am4.gbr
===================================================================
--- trunk/src/gerb/regression/am4.gbr (nonexistent)
+++ trunk/src/gerb/regression/am4.gbr (revision 1)
@@ -0,0 +1,16 @@
+G04 corner case: empty macro *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%AMFOO*
+0, comment *
+$3=($1-0.05)x1.5*
+%
+%AMBAR*
+%
+%ADD11FOO,0.50*%
+%ADD12BAR*%
+G54D11*X10000Y00000D03*
+G54D12*X20000Y00000D03*
+
+M02*
Index: trunk/src/gerb/regression/am5.gbr
===================================================================
--- trunk/src/gerb/regression/am5.gbr (nonexistent)
+++ trunk/src/gerb/regression/am5.gbr (revision 1)
@@ -0,0 +1,24 @@
+G04 zero sized (on centerline) rectangular lines *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+
+
+%AMP20*
+20,1,1,2,2,2,2,45*
+%
+
+
+%AMP21*
+21,1,1.0,1.0,1,2,45*
+%
+
+%ADD12P20*%
+%ADD13P21*%
+
+
+G54D12*X20000Y00000D03*
+G54D13*X30000Y00000D03*
+
+
+M02*
Index: trunk/src/gerb/regression/am6.gbr
===================================================================
--- trunk/src/gerb/regression/am6.gbr (nonexistent)
+++ trunk/src/gerb/regression/am6.gbr (revision 1)
@@ -0,0 +1,14 @@
+G04 macro aperture primitive 6 corner case *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+
+%AMP6*
+6,0,0,1.75x2,1,0.5,2,0.01,4.5,0*
+%
+
+%ADD11P6*%
+
+G54D11*X10000Y00000D03*
+
+M02*
Index: trunk/src/gerb/regression/am_polyexpr.gbr
===================================================================
--- trunk/src/gerb/regression/am_polyexpr.gbr (nonexistent)
+++ trunk/src/gerb/regression/am_polyexpr.gbr (revision 1)
@@ -0,0 +1,18 @@
+G04 polygonial macro aperture with the first X coord coming from a macro parameter *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+
+%AMPOLY*
+4,1,3,$1,1,6,1,8,0,$1,1,45*
+%
+
+
+%ADD11POLY,1*%
+%ADD12POLY,-9*%
+
+G54D11*X10000Y00000D03*
+G54D12*X20000Y00000D03*
+
+
+M02*
Index: trunk/src/gerb/regression/am_set.gbr
===================================================================
--- trunk/src/gerb/regression/am_set.gbr (nonexistent)
+++ trunk/src/gerb/regression/am_set.gbr (revision 1)
@@ -0,0 +1,20 @@
+G04 test AM set *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%AMFOO*
+0, comment *
+$2=1*
+$3=$1+1*
+$4=$1-1*
+1,1,0.5,0.0,0.0,0*
+1,1,$2,$3,$4,0*
+%
+%AMBAR*
+%
+%ADD11FOO,1*%
+%ADD12FOO,-1*%
+G54D11*X10000Y00000D03*
+G54D12*X20000Y00000D03*
+
+M02*
Index: trunk/src/gerb/regression/aper.gbr
===================================================================
--- trunk/src/gerb/regression/aper.gbr (nonexistent)
+++ trunk/src/gerb/regression/aper.gbr (revision 1)
@@ -0,0 +1,26 @@
+G04 flash and draw line with different regular apertures *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%ADD11C,1.0000*%
+%ADD12R,1.0000X0.5000*%
+%ADD13O,1.0000X0.5000*%
+%ADD14P,1.0000X3*%
+%ADD15P,1.0000X3X30*%
+%ADD16P,1.0000X3X30X0.5000*%
+
+G54D11*X10000Y01000D03*
+G54D11*X10000Y11000D02*Y03000D01*
+
+G54D12*X20000Y01000D03*
+G54D12*X20000Y11000D02*Y03000D01*
+
+G54D13*X30000Y01000D03*
+G54D13*X30000Y11000D02*Y03000D01*
+
+G54D14*X40000Y01000D03*
+G54D14*X40000Y11000D02*Y03000D01*
+
+G54D15*X50000Y01000D03*
+G54D15*X50000Y11000D02*Y03000D01*
+M02*
Index: trunk/src/gerb/regression/aper_hole.gbr
===================================================================
--- trunk/src/gerb/regression/aper_hole.gbr (nonexistent)
+++ trunk/src/gerb/regression/aper_hole.gbr (revision 1)
@@ -0,0 +1,25 @@
+G04 flash and draw line with different regular apertures *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%ADD11C,1.0000X0.4000*%
+%ADD12R,1.0000X0.5000X0.4000*%
+%ADD13O,1.0000X0.5000X0.4000*%
+%ADD14P,1.0000X3X0X0.4000*%
+%ADD15P,1.0000X3X30X0.4000*%
+
+G54D11*X10000Y01000D03*
+G54D11*X10000Y12000D02*Y12300D01*
+
+G54D12*X20000Y01000D03*
+G54D12*X20000Y12000D02*Y12300D01*
+
+G54D13*X30000Y01000D03*
+G54D13*X30000Y12000D02*Y12300D01*
+
+G54D14*X40000Y01000D03*
+G54D14*X40000Y12000D02*Y12300D01*
+
+G54D15*X50000Y01000D03*
+G54D15*X50000Y12000D02*Y12300D01*
+M02*
Index: trunk/src/gerb/regression/arc_all.gbr
===================================================================
--- trunk/src/gerb/regression/arc_all.gbr (nonexistent)
+++ trunk/src/gerb/regression/arc_all.gbr (revision 1)
@@ -0,0 +1,27 @@
+G04 start of page 2 for group 3 layer_idx 0 *
+G04 Title: (unknown), top_copper *
+G04 Creator: pcb-rnd 2.1.2 *
+G04 CreationDate: 2019-06-06 14:34:13 UTC *
+G04 For: *
+G04 Format: Gerber/RS-274X *
+G04 PCB-Dimensions: 30000 17500 *
+G04 PCB-Coordinate-Origin: lower left *
+%MOIN*%
+%FSLAX25Y25*%
+%LNTOP_COPPER_NONE_3*%
+%ADD11C,0.0010*%
+G54D11*
+
+G74*
+X07500Y7500D02*G02X08964Y11036I5000J0D01*G01*
+
+G74*
+X10000Y10000D02*G03X11000Y09000I1000J0000D01*G01*
+
+G75*
+X17500Y7500D02*G02X18964Y11036I5000J0D01*G01*
+
+G75*
+X22500Y7500D02*G03X23964Y11036I5000J0D01*G01*
+
+M02*
Index: trunk/src/gerb/regression/arc_g74.gbr
===================================================================
--- trunk/src/gerb/regression/arc_g74.gbr (nonexistent)
+++ trunk/src/gerb/regression/arc_g74.gbr (revision 1)
@@ -0,0 +1,23 @@
+G04 circle built of 4 single quandrant 1/4th arc *
+%MOMM*%
+%FSLAX23Y23*%
+%ADD11C,0.0500*%
+%ADD12C,0.0100*%
+
+G74*
+
+G04 9..12*
+G54D11*X09000Y10000D02*G02X10000Y11000I01000J00000D01*G01*
+
+
+G04 12..3*
+G54D12*X10000Y11000D02*G02X11000Y10000I00000J01000D01*G01*
+
+G04 3..6*
+G54D11*X11000Y10000D02*G02X10000Y09000I01000J00000D01*G01*
+
+
+G04 6..9*
+G54D12*X10000Y09000D02*G02X09000Y10000I00000J01000D01*G01*
+
+M02*
Index: trunk/src/gerb/regression/arc_g74p.gbr
===================================================================
--- trunk/src/gerb/regression/arc_g74p.gbr (nonexistent)
+++ trunk/src/gerb/regression/arc_g74p.gbr (revision 1)
@@ -0,0 +1,25 @@
+G04 circle built of 4 single quandrant 1/4th arc *
+%MOMM*%
+%FSLAX23Y23*%
+%ADD11C,0.0500*%
+
+G74*
+
+G54D11*
+G36*
+
+G04 9..12*
+X09000Y10000D02*G02X10000Y11000I01000J00000D01*G01*
+
+
+G04 12..3*
+X10000Y11000D02*G02X11000Y10000I00000J01000D01*G01*
+
+G04 3..6*
+X11000Y10000D02*G02X10000Y09000I01000J00000D01*G01*
+
+G04 6..9*
+X10000Y09000D02*G02X09000Y10000I00000J01000D01*G01*
+G37*
+
+M02*
Index: trunk/src/gerb/regression/arc_g75.gbr
===================================================================
--- trunk/src/gerb/regression/arc_g75.gbr (nonexistent)
+++ trunk/src/gerb/regression/arc_g75.gbr (revision 1)
@@ -0,0 +1,23 @@
+G04 circle built of 4 multi quandrant 1/4th arc *
+%MOMM*%
+%FSLAX23Y23*%
+%ADD11C,0.0500*%
+%ADD12C,0.0100*%
+
+G75*
+
+G04 9..12*
+G54D11*X09000Y10000D02*G02X10000Y11000I01000J00000D01*G01*
+
+
+G04 12..3*
+G54D12*X10000Y11000D02*G02X11000Y10000I00000J-01000D01*G01*
+
+G04 3..6*
+G54D11*X11000Y10000D02*G02X10000Y09000I-01000J00000D01*G01*
+
+
+G04 6..9*
+G54D12*X10000Y09000D02*G02X09000Y10000I00000J01000D01*G01*
+
+M02*
Index: trunk/src/gerb/regression/arc_g75b.gbr
===================================================================
--- trunk/src/gerb/regression/arc_g75b.gbr (nonexistent)
+++ trunk/src/gerb/regression/arc_g75b.gbr (revision 1)
@@ -0,0 +1,27 @@
+G04 circle built of 4 multi quandrant 3/4th thin arc + 1/4th thick arc *
+%MOMM*%
+%FSLAX23Y23*%
+%ADD11C,0.1000*%
+%ADD12C,0.0100*%
+
+G75*
+
+G04 9..12*
+G54D12*X09000Y10000D02*G03X10000Y11000I01000J00000D01*G01*
+G54D11*X09000Y10000D02*G02X10000Y11000I01000J00000D01*G01*
+
+
+G04 12..3*
+G54D12*X20000Y11000D02*G03X21000Y10000I00000J-01000D01*G01*
+G54D11*X20000Y11000D02*G02X21000Y10000I00000J-01000D01*G01*
+
+G04 3..6*
+G54D12*X31000Y10000D02*G03X30000Y09000I-01000J00000D01*G01*
+G54D11*X31000Y10000D02*G02X30000Y09000I-01000J00000D01*G01*
+
+
+G04 6..9*
+G54D12*X40000Y09000D02*G03X39000Y10000I00000J01000D01*G01*
+G54D11*X40000Y09000D02*G02X39000Y10000I00000J01000D01*G01*
+
+M02*
Index: trunk/src/gerb/regression/arc_g75bp.gbr
===================================================================
--- trunk/src/gerb/regression/arc_g75bp.gbr (nonexistent)
+++ trunk/src/gerb/regression/arc_g75bp.gbr (revision 1)
@@ -0,0 +1,37 @@
+G04 circle built of 4 multi quandrant 3/4th thin arc + 1/4th thick arc *
+%MOMM*%
+%FSLAX23Y23*%
+%ADD11C,0.1000*%
+%ADD12C,0.0100*%
+
+G75*
+
+G54D11*
+
+G04 9..12*
+G36*
+X09000Y10000D02*G03X10000Y11000I01000J00000D01*G01*
+X09000Y10000D02*G02X10000Y11000I01000J00000D01*G01*
+G37*
+
+
+G04 12..3*
+G36*
+X20000Y11000D02*G03X21000Y10000I00000J-01000D01*G01*
+X20000Y11000D02*G02X21000Y10000I00000J-01000D01*G01*
+G37*
+
+G04 3..6*
+G36*
+X31000Y10000D02*G03X30000Y09000I-01000J00000D01*G01*
+X31000Y10000D02*G02X30000Y09000I-01000J00000D01*G01*
+G37*
+
+
+G04 6..9*
+G36*
+X40000Y09000D02*G03X39000Y10000I00000J01000D01*G01*
+X40000Y09000D02*G02X39000Y10000I00000J01000D01*G01*
+G37*
+
+M02*
Index: trunk/src/gerb/regression/arc_g75p.gbr
===================================================================
--- trunk/src/gerb/regression/arc_g75p.gbr (nonexistent)
+++ trunk/src/gerb/regression/arc_g75p.gbr (revision 1)
@@ -0,0 +1,27 @@
+G04 circle built of 4 multi quandrant 1/4th arc *
+%MOMM*%
+%FSLAX23Y23*%
+%ADD11C,0.0500*%
+%ADD12C,0.0100*%
+
+G75*
+
+G54D11*
+G36*
+
+G04 9..12*
+X09000Y10000D02*G02X10000Y11000I01000J00000D01*G01*
+
+
+G04 12..3*
+X10000Y11000D02*G02X11000Y10000I00000J-01000D01*G01*
+
+G04 3..6*
+X11000Y10000D02*G02X10000Y09000I-01000J00000D01*G01*
+
+
+G04 6..9*
+X10000Y09000D02*G02X09000Y10000I00000J01000D01*G01*
+G37*
+
+M02*
Index: trunk/src/gerb/regression/crd_lead.gbr
===================================================================
--- trunk/src/gerb/regression/crd_lead.gbr (nonexistent)
+++ trunk/src/gerb/regression/crd_lead.gbr (revision 1)
@@ -0,0 +1,10 @@
+G04 coords with leading zeros: smaller flash in between the two larger ones *
+%MOMM*%
+%FSLAX23Y23*%
+%ADD11C,1.0000*%
+%ADD12C,0.5000*%
+
+G54D11*X00000Y00000D03*
+G54D11*X10000Y10000D03*
+G54D12*X5000Y5000D03*
+M02*
Index: trunk/src/gerb/regression/crd_tail.gbr
===================================================================
--- trunk/src/gerb/regression/crd_tail.gbr (nonexistent)
+++ trunk/src/gerb/regression/crd_tail.gbr (revision 1)
@@ -0,0 +1,10 @@
+G04 coords with leading zeros: smaller flash is far away from the two larger ones *
+%MOMM*%
+%FSTAX23Y23*%
+%ADD11C,1.0000*%
+%ADD12C,0.5000*%
+
+G54D11*X00000Y00000D03*
+G54D11*X10000Y10000D03*
+G54D12*X5000Y5000D03*
+M02*
Index: trunk/src/gerb/regression/poly1.gbr
===================================================================
--- trunk/src/gerb/regression/poly1.gbr (nonexistent)
+++ trunk/src/gerb/regression/poly1.gbr (revision 1)
@@ -0,0 +1,12 @@
+G04 polygon with thin pen *
+%MOIN*%
+%FSLAX25Y25*%
+%LNTOP_COPPER_NONE_3*%
+%ADD11C,0.0001*%
+G54D11*G36*
+X32500Y20000D02*Y5000D01*
+X2500D01*
+X17500Y20000D01*
+X32500D01*
+G37*
+M02*
Index: trunk/src/gerb/regression/polyarc.gbr
===================================================================
--- trunk/src/gerb/regression/polyarc.gbr (nonexistent)
+++ trunk/src/gerb/regression/polyarc.gbr (revision 1)
@@ -0,0 +1,12 @@
+G04 polygon with an arc and a line in the contour *
+%MOMM*%
+%FSLAX43Y43*%
+%LNTOP_COPPER_NONE_3*%
+%ADD11C,0.0100*%
+G54D11*
+G36*
+G75*
+X33020Y33020D02*X1905Y1905D01*
+X1905Y1905D02*G75*G02X33020Y33020I31115J0D01*G01*
+G37*
+M02*
Index: trunk/src/gerb/regression/steprep.gbr
===================================================================
--- trunk/src/gerb/regression/steprep.gbr (nonexistent)
+++ trunk/src/gerb/regression/steprep.gbr (revision 1)
@@ -0,0 +1,12 @@
+G04 step and repeat with explicit termination *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%ADD11C,0.7000*%
+%SRX3Y2I3.0J6.0*%
+G54D11*X10000Y00000D03*
+G54D11*X10000Y01000D02*Y02000D01*
+%SR*%
+
+G54D11*X10000Y01000D02*X12000D01*
+M02*
Index: trunk/src/gerb/regression/steprep2.gbr
===================================================================
--- trunk/src/gerb/regression/steprep2.gbr (nonexistent)
+++ trunk/src/gerb/regression/steprep2.gbr (revision 1)
@@ -0,0 +1,9 @@
+G04 step and repeat with implicit termination *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%ADD11C,0.7000*%
+%SRX3Y2I3.0J6.0*%
+G54D11*X10000Y00000D03*
+G54D11*X10000Y01000D02*Y02000D01*
+M02*
Index: trunk/src/gerb/regression/steprep3.gbr
===================================================================
--- trunk/src/gerb/regression/steprep3.gbr (nonexistent)
+++ trunk/src/gerb/regression/steprep3.gbr (revision 1)
@@ -0,0 +1,14 @@
+G04 recursive step and repeat seems to be impossible, each new SR closes the old *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%ADD11C,0.7000*%
+%ADD12C,0.1000*%
+%SRX2Y2I10.0J10.0*%
+G54D12*X10000Y01000D02*X12000D01*
+%SRX2Y2I3.0J6.0*%
+G54D11*X10000Y00000D03*
+G54D11*X10000Y01000D02*Y02000D01*
+%SR*%
+%SR*%
+M02*
Index: trunk/src/gerb/regression/steprep4.gbr
===================================================================
--- trunk/src/gerb/regression/steprep4.gbr (nonexistent)
+++ trunk/src/gerb/regression/steprep4.gbr (revision 1)
@@ -0,0 +1,17 @@
+G04 leave drawing state in LPC at the end of a SR block and see how the next block starts:
+G04 conclusion: states are SR-local *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%ADD11C,0.7000*%
+%ADD12C,0.2000*%
+
+%LPD*%
+
+%SRX3Y2I3.0J6.0*%
+G54D11*X10000Y01000D02*Y02000D01*
+%LPC*%
+G54D12*X10000Y01000D02*Y02000D01*
+%SR*%
+
+M02*
Index: trunk/src/gerb/regression/steprep5.gbr
===================================================================
--- trunk/src/gerb/regression/steprep5.gbr (nonexistent)
+++ trunk/src/gerb/regression/steprep5.gbr (revision 1)
@@ -0,0 +1,17 @@
+G04 leave drawing state in LPC before the SR block and see if it is inherited
+G04 conclusion: SR-block states are inherited from parent *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%ADD11C,0.5000*%
+%ADD12C,2.0000*%
+
+%LPD*%
+G54D12*X10000Y01010D02*X60000D01*
+%LPC*%
+%SRX5Y1I3.0J0.0*%
+G54D11*X10000Y01000D02*Y03000D01*
+%SR*%
+G54D11*X10000Y01010D02*X20000D01*
+
+M02*
Index: trunk/src/gerb/regression/steprep6.gbr
===================================================================
--- trunk/src/gerb/regression/steprep6.gbr (nonexistent)
+++ trunk/src/gerb/regression/steprep6.gbr (revision 1)
@@ -0,0 +1,17 @@
+G04 test whether SR goes in x-y or y-x order, by checking overlaps *
+G04 conclusion: inner loop should be y, from 0 up *
+%MOMM*%
+%FSLAX23Y23*%
+%LNTOP*%
+%ADD11C,0.7000*%
+%ADD12C,0.3000*%
+
+%LPD*%
+
+%SRX3Y2I0.25J0.75*%
+G54D11*X10000Y01000D02*Y02000D01*
+%LPC*%
+G54D12*X10000Y01000D02*Y02000D01*
+%SR*%
+
+M02*
Index: trunk/src/gui/camv_gui.c
===================================================================
--- trunk/src/gui/camv_gui.c (nonexistent)
+++ trunk/src/gui/camv_gui.c (revision 1)
@@ -0,0 +1,180 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ * (copied from pcb-rnd by the author)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+
+#include "event.h"
+#include "actions.h"
+#include "hidlib.h"
+#include "hidlib_conf.h"
+#include "compat_misc.h"
+#include "compat_fs.h"
+#include "globalconst.h"
+
+#include "data.h"
+#include "plug_io_act.h"
+
+#include "layersel.h"
+
+static const char *layersel_cookie = "camv_gui/layersel";
+static const char *camv_gui_cookie = "camv_gui";
+
+#define NOGUI() \
+do { \
+ if ((pcb_gui == NULL) || (!pcb_gui->gui)) { \
+ PCB_ACT_IRES(1); \
+ return 0; \
+ } \
+ PCB_ACT_IRES(0); \
+} while(0)
+
+const char pcb_acts_Popup[] = "Popup(MenuName, [obj-type])";
+const char pcb_acth_Popup[] = "Bring up the popup menu specified by MenuName, optionally modified with the object type under the cursor.\n";
+fgw_error_t pcb_act_Popup(fgw_arg_t *res, int argc, fgw_arg_t *argv)
+{
+ char name[256], name2[256];
+ const char *tn = NULL, *a0, *a1 = NULL;
+ int r = 1;
+ enum {
+ CTX_NONE,
+ CTX_OBJ_TYPE
+ } ctx_sens = CTX_NONE;
+
+ NOGUI();
+
+ if (argc != 2 && argc != 3)
+ PCB_ACT_FAIL(Popup);
+
+ PCB_ACT_CONVARG(1, FGW_STR, Popup, a0 = argv[1].val.str);
+ PCB_ACT_MAY_CONVARG(2, FGW_STR, Popup, a1 = argv[2].val.str);
+
+ *name = '\0';
+ *name2 = '\0';
+
+ if (argc == 3) {
+ if (strcmp(a1, "obj-type") == 0) ctx_sens = CTX_OBJ_TYPE;
+ }
+
+ if (strlen(a0) < sizeof(name) - 32) {
+ switch(ctx_sens) {
+ case CTX_OBJ_TYPE:
+ {
+ pcb_coord_t x, y;
+/* pcb_objtype_t type;
+ void *o1, *o2, *o3;*/
+ pcb_hid_get_coords("context sensitive popup: select object", &x, &y, 0);
+#if 0
+ type = pcb_search_screen(x, y, PCB_OBJ_PSTK | PCB_OBJ_SUBC_PART, &o1, &o2, &o3);
+ if (type == 0)
+ type = pcb_search_screen(x, y, PCB_OBJ_CLASS_REAL, &o1, &o2, &o3);
+
+ if (type == 0)
+ tn = "none";
+ else
+ tn = pcb_obj_type_name(type);
+#endif
+ sprintf(name, "/popups/%s-%s", a0, tn);
+ sprintf(name2, "/popups/%s-misc", a0);
+ }
+ break;
+ case CTX_NONE:
+ sprintf(name, "/popups/%s", a0);
+ break;
+
+ }
+ }
+
+ if (*name != '\0')
+ r = pcb_gui->open_popup(pcb_gui, name);
+ if ((r != 0) && (*name2 != '\0'))
+ r = pcb_gui->open_popup(pcb_gui, name2);
+
+ PCB_ACT_IRES(r);
+ return 0;
+}
+
+static char *dup_cwd(void)
+{
+ char tmp[PCB_PATH_MAX + 1];
+ return pcb_strdup(pcb_get_wd(tmp));
+}
+
+static const char pcb_acts_Load[] = "Load()\n" "Load(Project|Layer)";
+static const char pcb_acth_Load[] = "Load a camv project or a layer from a user-selected file.";
+static fgw_error_t pcb_act_Load(fgw_arg_t *res, int argc, fgw_arg_t *argv)
+{
+ static char *last_project = NULL, *last_layer = NULL;
+ const char *function = "Layer";
+ char *name = NULL;
+
+ if (last_layer == NULL) last_layer = dup_cwd();
+ if (last_project == NULL) last_project = dup_cwd();
+
+ /* Called with both function and file name -> no gui */
+ if (argc > 2)
+ return PCB_ACT_CALL_C(pcb_act_LoadFrom, res, argc, argv);
+
+ PCB_ACT_MAY_CONVARG(1, FGW_STR, Load, function = argv[1].val.str);
+
+ if (pcb_strcasecmp(function, "Layer") == 0)
+ name = pcb_gui->fileselect(pcb_gui, "Load layer", "Import a layer from file", last_layer, NULL, NULL, "layer", PCB_HID_FSD_READ, NULL);
+ else if (pcb_strcasecmp(function, "Project") == 0)
+ name = pcb_gui->fileselect(pcb_gui, "Load a project file", "load project (all layers) from file", last_project, ".lht", NULL, "project", PCB_HID_FSD_READ, NULL);
+ else {
+ pcb_message(PCB_MSG_ERROR, "Invalid subcommand for Load(): '%s'\n", function);
+ PCB_ACT_IRES(1);
+ return 0;
+ }
+
+ if (name != NULL) {
+ if (pcbhl_conf.rc.verbose)
+ fprintf(stderr, "Load: Calling LoadFrom(%s, %s)\n", function, name);
+ pcb_actionl("LoadFrom", function, name, NULL);
+ free(name);
+ }
+
+ PCB_ACT_IRES(0);
+ return 0;
+}
+
+static pcb_action_t camv_gui_action_list[] = {
+ {"Popup", pcb_act_Popup, pcb_acth_Popup, pcb_acts_Popup},
+ {"Load", pcb_act_Load, pcb_acth_Load, pcb_acts_Load},
+ {"Layer", pcb_act_Layer, pcb_acth_Layer, pcb_acts_Layer}
+};
+PCB_REGISTER_ACTIONS(camv_gui_action_list, camv_gui_cookie)
+
+#include "dolists.h"
+
+void camv_gui_init()
+{
+ pcb_event_bind(PCB_EVENT_GUI_INIT, camv_layersel_gui_init_ev, NULL, layersel_cookie);
+ pcb_event_bind(PCB_EVENT_LAYERS_CHANGED, camv_layersel_layer_chg_ev, NULL, layersel_cookie);
+ PCB_REGISTER_ACTIONS(camv_gui_action_list, camv_gui_cookie);
+}
Index: trunk/src/gui/layersel.c
===================================================================
--- trunk/src/gui/layersel.c (nonexistent)
+++ trunk/src/gui/layersel.c (revision 1)
@@ -0,0 +1,475 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ * (copied from pcb-rnd by the author)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "hid.h"
+#include "hid_cfg.h"
+#include "hid_dad.h"
+
+#include "actions.h"
+#include "data.h"
+#include "event.h"
+#include "hidlib_conf.h"
+
+#include "layersel.h"
+
+static const char *xpm_up[] = {
+"10 10 3 1",
+" c None",
+"@ c #6EA5D7",
+"+ c #000000",
+" ++ ",
+" +@@+ ",
+" +@@@@+ ",
+" +@@@@@@+ ",
+"+@@@@@@@@+",
+"++++@@++++",
+" +@@+ ",
+" +@@+ ",
+" +@@+ ",
+" ++++ ",
+};
+
+static const char *xpm_upmost[] = {
+"10 10 3 1",
+" c None",
+"@ c #6EA5D7",
+"+ c #000000",
+"++++++++++",
+"+@@@@@@@@+",
+"++++@@++++",
+" +@@@@@@+ ",
+"+@@@@@@@@+",
+"++++@@++++",
+" +@@+ ",
+" +@@+ ",
+" +@@+ ",
+" ++++ ",
+};
+
+static const char *xpm_down[] = {
+"10 10 3 1",
+" c None",
+"@ c #6EA5D7",
+"+ c #000000",
+" ++++ ",
+" +@@+ ",
+" +@@+ ",
+" +@@+ ",
+"++++@@++++",
+"+@@@@@@@@+",
+" +@@@@@@+ ",
+" +@@@@+ ",
+" +@@+ ",
+" ++ ",
+};
+
+static const char *xpm_downmost[] = {
+"10 10 3 1",
+" c None",
+"@ c #6EA5D7",
+"+ c #000000",
+" ++++ ",
+" +@@+ ",
+" +@@+ ",
+" +@@+ ",
+"++++@@++++",
+"+@@@@@@@@+",
+" +@@@@@@+ ",
+"++++@@++++",
+"+@@@@@@@@+",
+"++++++++++",
+};
+
+static const char *xpm_add[] = {
+"10 10 3 1",
+" c None",
+"@ c #6EA5D7",
+"+ c #000000",
+" ++++ ",
+" +@@+ ",
+" +@@+ ",
+"++++@@++++",
+"+@@@@@@@@+",
+"+@@@@@@@@+",
+"++++@@++++",
+" +@@+ ",
+" +@@+ ",
+" ++++ ",
+};
+
+static const char *xpm_del[] = {
+"10 10 3 1",
+" c None",
+"@ c #6EA5D7",
+"+ c #000000",
+" ",
+" ",
+" ",
+"++++++++++",
+"+@@@@@@@@+",
+"+@@@@@@@@+",
+"++++++++++",
+" ",
+" ",
+" ",
+};
+
+
+
+typedef struct {
+ char buf[32][20];
+ const char *xpm[32];
+} gen_xpm_t;
+
+typedef struct layersel_ctx_s layersel_ctx_t;
+
+typedef struct {
+ int wvis_on, wvis_off, wlab;
+ int wunsel, wsel;
+ gen_xpm_t on, off;
+ pcb_cardinal_t lid;
+ layersel_ctx_t *ls;
+} ls_layer_t;
+
+
+struct layersel_ctx_s {
+ pcb_hid_dad_subdialog_t sub;
+ camv_design_t *camv;
+ int sub_inited;
+ int wbut_up, wbut_down, wbut_top, wbut_bottom, wbut_load, wbut_remove;
+ int lock_vis, lock_sel;
+ int selected; /* layer idx (lid) of the currently selected layer */
+ vtp0_t layers; /* -> ls_layer_t */
+};
+
+static layersel_ctx_t layersel;
+
+static void lys_update_vis(camv_design_t *camv, ls_layer_t *lys)
+{
+ camv_layer_t **ly = (camv_layer_t **)vtp0_get(&camv->layers, lys->lid, 0);
+ int hide_on = 1, hide_off = 1;
+
+ if ((ly != NULL) && (*ly != NULL)) {
+ hide_on = !(*ly)->vis;
+ hide_off = !!(*ly)->vis;
+ }
+
+ pcb_gui->attr_dlg_widget_hide(lys->ls->sub.dlg_hid_ctx, lys->wvis_on, hide_on);
+ pcb_gui->attr_dlg_widget_hide(lys->ls->sub.dlg_hid_ctx, lys->wvis_off, hide_off);
+}
+
+static void layer_vis_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr)
+{
+ ls_layer_t *lys = attr->user_data;
+ camv_design_t *camv = lys->ls->camv;
+ camv_layer_t **ly = (camv_layer_t **)vtp0_get(&camv->layers, lys->lid, 0);
+
+ if ((ly == NULL) || (*ly == NULL))
+ return;
+
+ lys->ls->lock_vis++;
+ camv_layer_set_vis(camv, lys->lid, !(*ly)->vis, 1);
+ lys->ls->lock_vis--;
+
+ lys_update_vis(camv, lys);
+ camv_hid_redraw(camv);
+}
+
+static void layer_unselect(layersel_ctx_t *ls)
+{
+ ls_layer_t **lys;
+ if (ls->selected < 0)
+ return;
+
+ lys = (ls_layer_t **)vtp0_get(&ls->layers, ls->selected, 0);
+ if (lys != NULL)
+ pcb_gui->attr_dlg_widget_state(ls->sub.dlg_hid_ctx, (*lys)->wlab, 1);
+ ls->selected = -1;
+}
+
+static void layer_select(ls_layer_t *lys)
+{
+ layer_unselect(lys->ls);
+ lys->ls->selected = lys->lid;
+ pcb_gui->attr_dlg_widget_state(lys->ls->sub.dlg_hid_ctx, lys->wlab, 2);
+}
+
+static void layer_sel_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr)
+{
+ layer_select((ls_layer_t *)attr->user_data);
+}
+
+
+static void layer_right_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr)
+{
+ layer_select((ls_layer_t *)attr->user_data);
+ pcb_actionl("Popup", "layer", NULL);
+}
+
+static void layer_button_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr)
+{
+ layersel_ctx_t *ls = attr->user_data;
+ int wid = attr - ls->sub.dlg;
+ if (wid == ls->wbut_up) pcb_actionl("Layer", "up", NULL);
+ else if (wid == ls->wbut_down) pcb_actionl("Layer", "down", NULL);
+ else if (wid == ls->wbut_top) pcb_actionl("Layer", "top", NULL);
+ else if (wid == ls->wbut_bottom) pcb_actionl("Layer", "bottom", NULL);
+ else if (wid == ls->wbut_load) pcb_actionl("Load", "Layer", NULL);
+ else if (wid == ls->wbut_remove) pcb_actionl("Layer", "remove", NULL);
+ else pcb_message(PCB_MSG_ERROR, "Internal error: layer_button_cb(): invalid wid\n");
+}
+
+/* draw a visibility box: filled or partially filled with layer color */
+static void layer_vis_box(gen_xpm_t *dst, int filled, const pcb_color_t *color, int brd, int hatch, int width, int height, int slant)
+{
+ int max_height = height;
+ char *p;
+ unsigned int w, line = 0, n;
+
+ pcb_snprintf(dst->buf[line++], 20, "%d %d 4 1", width, height);
+ strcpy(dst->buf[line++], ". c None");
+ strcpy(dst->buf[line++], "u c None");
+ strcpy(dst->buf[line++], "b c #000000");
+ pcb_snprintf(dst->buf[line++], 20, "c c #%02X%02X%02X", color->r, color->g, color->b);
+
+ while (height--) {
+ w = width;
+ p = dst->buf[line++];
+ while (w--) {
+ if ((height < brd) || (height >= max_height-brd) || (w < brd) || (w >= width-brd))
+ *p = 'b'; /* frame */
+ else if ((hatch) && (((w - height) % 4) == 0))
+ *p = '.';
+ else if ((width-w+slant < height) || (filled))
+ *p = 'c'; /* layer color fill (full or up-left triangle) */
+ else
+ *p = 'u'; /* the unfilled part when triangle should be transparent */
+ p++;
+ }
+ *p = '\0';
+ }
+
+ for(n=0; n < line; n++)
+ dst->xpm[n] = dst->buf[n];
+}
+
+static void layersel_create_layer(layersel_ctx_t *ls, ls_layer_t *lys, const char *name, const pcb_color_t *color, int brd, int hatch)
+{
+ layer_vis_box(&lys->on, 1, color, brd, hatch, 16, 16, 5);
+ layer_vis_box(&lys->off, 0, color, brd, hatch, 16, 16, 5);
+
+ PCB_DAD_BEGIN_HBOX(ls->sub.dlg);
+ PCB_DAD_PICTURE(ls->sub.dlg, lys->on.xpm);
+ lys->wvis_on = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, lys);
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_vis_cb);
+ PCB_DAD_PICTURE(ls->sub.dlg, lys->off.xpm);
+ lys->wvis_off = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, lys);
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_vis_cb);
+ PCB_DAD_LABEL(ls->sub.dlg, name);
+ lys->wlab = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, lys);
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_sel_cb);
+ PCB_DAD_RIGHT_CB(ls->sub.dlg, layer_right_cb);
+ PCB_DAD_END(ls->sub.dlg);
+}
+
+static void layersel_docked_create(layersel_ctx_t *ls, camv_design_t *camv)
+{
+ long n, i; /* must be signed */
+
+ PCB_DAD_BEGIN_VBOX(ls->sub.dlg);
+ PCB_DAD_COMPFLAG(ls->sub.dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL);
+
+ /* build layers in reverse order (rendering needs to be fast so goes from front to back) */
+ for(i = 0, n = camv->layers.used-1; n >= 0; n--) {
+ camv_layer_t *ly = camv->layers.array[n];
+ ls_layer_t *lys, **lysp;
+
+ if (ly->sub) continue;
+ lysp = (ls_layer_t **)vtp0_get(&ls->layers, n, 1);
+ if (*lysp == NULL)
+ *lysp = calloc(sizeof(ls_layer_t), 1);
+ lys = *lysp;
+ lys->lid = n;
+ lys->ls = ls;
+ layersel_create_layer(ls, lys, ly->name, &ly->color, 1, 0);
+ i++;
+ }
+
+ PCB_DAD_BEGIN_VBOX(ls->sub.dlg);
+ PCB_DAD_COMPFLAG(ls->sub.dlg, PCB_HATF_EXPFILL);
+ PCB_DAD_END(ls->sub.dlg);
+
+
+ PCB_DAD_BEGIN_HBOX(ls->sub.dlg);
+ PCB_DAD_PICBUTTON(ls->sub.dlg, xpm_up);
+ PCB_DAD_HELP(ls->sub.dlg, "Move layer up in the stack");
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_button_cb);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, ls);
+ ls->wbut_up = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_PICBUTTON(ls->sub.dlg, xpm_down);
+ PCB_DAD_HELP(ls->sub.dlg, "Move layer down in the stack");
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_button_cb);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, ls);
+ ls->wbut_down = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_PICBUTTON(ls->sub.dlg, xpm_upmost);
+ PCB_DAD_HELP(ls->sub.dlg, "Move layer to the top of the stack");
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_button_cb);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, ls);
+ ls->wbut_top = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_PICBUTTON(ls->sub.dlg, xpm_downmost);
+ PCB_DAD_HELP(ls->sub.dlg, "Move layer to the bottom of the stack");
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_button_cb);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, ls);
+ ls->wbut_bottom = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_PICBUTTON(ls->sub.dlg, xpm_add);
+ PCB_DAD_HELP(ls->sub.dlg, "Add (load) a new layer");
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_button_cb);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, ls);
+ ls->wbut_load = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_PICBUTTON(ls->sub.dlg, xpm_del);
+ PCB_DAD_HELP(ls->sub.dlg, "Del (remove) a layer");
+ PCB_DAD_CHANGE_CB(ls->sub.dlg, layer_button_cb);
+ PCB_DAD_SET_ATTR_FIELD(ls->sub.dlg, user_data, ls);
+ ls->wbut_remove = PCB_DAD_CURRENT(ls->sub.dlg);
+ PCB_DAD_BEGIN_HBOX(ls->sub.dlg);
+ PCB_DAD_COMPFLAG(ls->sub.dlg, PCB_HATF_EXPFILL);
+ PCB_DAD_END(ls->sub.dlg);
+ PCB_DAD_END(ls->sub.dlg);
+ PCB_DAD_END(ls->sub.dlg);
+ PCB_DAD_DEFSIZE(ls->sub.dlg, 210, 200);
+ PCB_DAD_MINSIZE(ls->sub.dlg, 100, 100);
+}
+
+static void layersel_update_vis(layersel_ctx_t *ls, camv_design_t *camv)
+{
+ long n;
+ for(n = 0; n < ls->layers.used; n++)
+ lys_update_vis(camv, ls->layers.array[n]);
+}
+
+static void layersel_build(void)
+{
+ layersel_docked_create(&layersel, &camv);
+ if (pcb_hid_dock_enter(&layersel.sub, PCB_HID_DOCK_LEFT, "layersel") == 0) {
+ layersel.sub_inited = 1;
+ layersel_update_vis(&layersel, &camv);
+ }
+}
+
+void camv_layersel_gui_init_ev(pcb_hidlib_t *hidlib, void *user_data, int argc, pcb_event_arg_t argv[])
+{
+ if ((PCB_HAVE_GUI_ATTR_DLG) && (pcb_gui->get_menu_cfg != NULL)) {
+ layersel.camv = &camv;
+ layersel_build();
+ }
+}
+
+void camv_layersel_vis_chg_ev(pcb_hidlib_t *hidlib, void *user_data, int argc, pcb_event_arg_t argv[])
+{
+ if ((!layersel.sub_inited) || (layersel.lock_vis > 0))
+ return;
+ layersel_update_vis(&layersel, &camv);
+}
+
+void camv_layersel_layer_chg_ev(pcb_hidlib_t *hidlib, void *user_data, int argc, pcb_event_arg_t argv[])
+{
+ if ((PCB_HAVE_GUI_ATTR_DLG) && (pcb_gui->get_menu_cfg != NULL) && (layersel.sub_inited)) {
+ pcb_hid_dock_leave(&layersel.sub);
+ layersel.sub_inited = 0;
+ layersel_build();
+ }
+}
+
+static void layer_move(int dst)
+{
+ int step, n, src = layersel.selected;
+ camv_design_t *camv = layersel.camv;
+ camv_layer_t *dst_ly = camv->layers.array[src];
+
+ step = dst > src ? 1 : -1;
+ for(n = src; step > 0 ? (n < dst) : (n > dst); n += step)
+ camv->layers.array[n] = camv->layers.array[n+step];
+ camv->layers.array[dst] = dst_ly;
+
+ pcb_event(&layersel.camv->hidlib, PCB_EVENT_LAYERS_CHANGED, NULL);
+ layer_select(layersel.layers.array[dst]);
+ camv_hid_redraw(camv);
+}
+
+const char pcb_acts_Layer[] = "Layer([up|down|top|bottom|del])";
+const char pcb_acth_Layer[] = "Move or remove the current layer\n";
+fgw_error_t pcb_act_Layer(fgw_arg_t *res, int argc, fgw_arg_t *argv)
+{
+ const char *cmd = NULL;
+ camv_design_t *camv = layersel.camv;
+
+ if (argc != 2)
+ PCB_ACT_FAIL(Layer);
+
+ PCB_ACT_CONVARG(1, FGW_STR, Layer, cmd = argv[1].val.str);
+
+ if (strcmp(cmd, "down") == 0) {
+ if (layersel.selected < 0) goto nolayer;
+ if (layersel.selected == 0) goto nop;
+ layer_move(layersel.selected-1);
+ }
+ else if (strcmp(cmd, "up") == 0) {
+ if (layersel.selected < 0) goto nolayer;
+ if (layersel.selected == camv->layers.used-1) goto nop;
+ layer_move(layersel.selected+1);
+ }
+ else if (strcmp(cmd, "bottom") == 0) {
+ if (layersel.selected < 0) goto nolayer;
+ if (layersel.selected == 0) goto nop;
+ layer_move(0);
+ }
+ else if (strcmp(cmd, "top") == 0) {
+ if (layersel.selected < 0) goto nolayer;
+ if (layersel.selected == camv->layers.used-1) goto nop;
+ layer_move(camv->layers.used-1);
+ }
+ else {
+ PCB_ACT_FAIL(Layer);
+ }
+
+ nop:;
+ PCB_ACT_IRES(0);
+ return 0;
+
+ nolayer:;
+ pcb_message(PCB_MSG_ERROR, "no layer selected");
+ PCB_ACT_IRES(-1);
+ return 0;
+}
Index: trunk/src/gui/layersel.h
===================================================================
--- trunk/src/gui/layersel.h (nonexistent)
+++ trunk/src/gui/layersel.h (revision 1)
@@ -0,0 +1,8 @@
+void camv_layersel_gui_init_ev(pcb_hidlib_t *hidlib, void *user_data, int argc, pcb_event_arg_t argv[]);
+void camv_layersel_vis_chg_ev(pcb_hidlib_t *hidlib, void *user_data, int argc, pcb_event_arg_t argv[]);
+void camv_layersel_layer_chg_ev(pcb_hidlib_t *hidlib, void *user_data, int argc, pcb_event_arg_t argv[]);
+
+
+extern const char pcb_acts_Layer[];
+extern const char pcb_acth_Layer[];
+fgw_error_t pcb_act_Layer(fgw_arg_t *res, int argc, fgw_arg_t *argv);
Index: trunk/src/gui_act.c
===================================================================
--- trunk/src/gui_act.c (nonexistent)
+++ trunk/src/gui_act.c (revision 1)
@@ -0,0 +1,152 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "actions.h"
+#include "compat_misc.h"
+
+#include "data.h"
+
+#define NOGUI() \
+do { \
+ if ((pcb_gui == NULL) || (!pcb_gui->gui)) { \
+ PCB_ACT_IRES(1); \
+ return 0; \
+ } \
+ PCB_ACT_IRES(0); \
+} while(0)
+
+static const char pcb_acts_Quit[] = "Quit()";
+static const char pcb_acth_Quit[] = "Quits the application.";
+static fgw_error_t pcb_act_Quit(fgw_arg_t *res, int argc, fgw_arg_t *argv)
+{
+ exit(0);
+}
+
+const char pcb_acts_Pan[] = "Pan(Mode)";
+const char pcb_acth_Pan[] = "Start or stop panning (Mode = 1 to start, 0 to stop)\n";
+fgw_error_t pcb_act_Pan(fgw_arg_t *res, int argc, fgw_arg_t *argv)
+{
+ int mode;
+ pcb_coord_t x, y;
+
+ NOGUI();
+
+ pcb_hid_get_coords("Click on a place to pan", &x, &y, 0);
+
+ PCB_ACT_CONVARG(1, FGW_INT, Pan, mode = argv[1].val.nat_int);
+ pcb_gui->pan_mode(pcb_gui, x, y, mode);
+
+ PCB_ACT_IRES(0);
+ return 0;
+}
+
+const char pcb_acts_Zoom[] =
+ "Zoom()\n"
+ "Zoom([+|-|=]factor)\n"
+ "Zoom(x1, y1, x2, y2)\n"
+ "Zoom(?)\n"
+ "Zoom(get)\n";
+const char pcb_acth_Zoom[] = "GUI zoom";
+fgw_error_t pcb_act_Zoom(fgw_arg_t *res, int argc, fgw_arg_t *argv)
+{
+ const char *vp, *ovp;
+ double v;
+ pcb_coord_t x = 0, y = 0;
+
+ NOGUI();
+
+ if (argc < 2) {
+ pcb_gui->zoom_win(pcb_gui, 0, 0, camv.hidlib.size_x, camv.hidlib.size_y, 1);
+ return 0;
+ }
+
+ if (argc == 5) {
+ pcb_coord_t x1, y1, x2, y2;
+
+ PCB_ACT_CONVARG(1, FGW_COORD, Zoom, x1 = fgw_coord(&argv[1]));
+ PCB_ACT_CONVARG(2, FGW_COORD, Zoom, y1 = fgw_coord(&argv[2]));
+ PCB_ACT_CONVARG(3, FGW_COORD, Zoom, x2 = fgw_coord(&argv[3]));
+ PCB_ACT_CONVARG(4, FGW_COORD, Zoom, y2 = fgw_coord(&argv[4]));
+
+ pcb_gui->zoom_win(pcb_gui, x1, y1, x2, y2, 1);
+ return 0;
+ }
+
+ if (argc > 2)
+ PCB_ACT_FAIL(Zoom);
+
+ PCB_ACT_CONVARG(1, FGW_STR, Zoom, ovp = vp = argv[1].val.str);
+
+ if (*vp == '?') {
+ pcb_message(PCB_MSG_INFO, "Current zoom level (coord-per-pix): %$mm\n", pcb_gui->coord_per_pix);
+ return 0;
+ }
+
+ if (pcb_strcasecmp(argv[1].val.str, "get") == 0) {
+ res->type = FGW_DOUBLE;
+ res->val.nat_double = pcb_gui->coord_per_pix;
+ return 0;
+ }
+
+ if (*vp == '+' || *vp == '-' || *vp == '=')
+ vp++;
+ v = strtod(vp, NULL);
+ if (v <= 0)
+ return FGW_ERR_ARG_CONV;
+
+ pcb_hid_get_coords("Select zoom center", &x, &y, 0);
+ switch (ovp[0]) {
+ case '-':
+ pcb_gui->zoom(pcb_gui, x, y, 1 / v, 1);
+ break;
+ default:
+ case '+':
+ pcb_gui->zoom(pcb_gui, x, y, v, 1);
+ break;
+ case '=':
+ pcb_gui->zoom(pcb_gui, x, y, v, 0);
+ break;
+ }
+
+ PCB_ACT_IRES(0);
+ return 0;
+}
+
+static pcb_action_t gui_action_list[] = {
+ {"Quit", pcb_act_Quit, pcb_acth_Quit, pcb_acts_Quit},
+ {"Pan", pcb_act_Pan, pcb_acth_Pan, pcb_acts_Pan},
+ {"Zoom", pcb_act_Zoom, pcb_acth_Zoom, pcb_acts_Zoom}
+};
+
+PCB_REGISTER_ACTIONS(gui_action_list, NULL)
+
+#include "dolists.h"
+
+void gui_act_init(void)
+{
+ PCB_REGISTER_ACTIONS(gui_action_list, NULL)
+}
+
Index: trunk/src/gui_act.h
===================================================================
--- trunk/src/gui_act.h (nonexistent)
+++ trunk/src/gui_act.h (revision 1)
@@ -0,0 +1 @@
+void gui_act_init(void);
Index: trunk/src/obj_any.c
===================================================================
--- trunk/src/obj_any.c (nonexistent)
+++ trunk/src/obj_any.c (revision 1)
@@ -0,0 +1,50 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+
+#include "obj_any.h"
+
+void camv_obj_add_to_layer(camv_layer_t *ly, camv_any_obj_t *obj)
+{
+ assert(obj->proto.parent_layer == NULL);
+ assert(obj->proto.parent_obj == NULL);
+ obj->proto.parent_layer = ly;
+ camv_rtree_insert(&ly->objs, obj, camv_obj_bbox(obj));
+}
+
+
+camv_any_obj_t *camv_obj_dup(const camv_any_obj_t *src)
+{
+ camv_any_obj_t *dst = src->proto.calls->alloc();
+ src->proto.calls->copy(dst, src);
+ dst->proto.parent_layer = NULL;
+ dst->proto.parent_obj = NULL;
+ return dst;
+}
+
Index: trunk/src/obj_any.h
===================================================================
--- trunk/src/obj_any.h (nonexistent)
+++ trunk/src/obj_any.h (revision 1)
@@ -0,0 +1,91 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_OBJ_ANY_H
+#define CAMV_OBJ_ANY_H
+
+#include
+
+#include "camv_typedefs.h"
+#include "data.h"
+#include "obj_common.h"
+#include "obj_arc.h"
+#include "obj_line.h"
+#include "obj_poly.h"
+#include "obj_grp.h"
+
+typedef struct camv_proto_s {
+ CAMV_ANY_PRIMITIVE_FIELDS;
+} camv_proto_t;
+
+union camv_any_obj_u {
+ camv_proto_t proto;
+ camv_arc_t arc;
+ camv_line_t line;
+ camv_poly_t poly;
+ camv_grp_t grp;
+};
+
+void camv_obj_add_to_layer(camv_layer_t *ly, camv_any_obj_t *obj);
+
+/* Allocate a new object and copy all fields from src, except for parent data */
+camv_any_obj_t *camv_obj_dup(const camv_any_obj_t *src);
+
+PCB_INLINE camv_layer_t *camv_obj_parent_layer(const camv_any_obj_t *obj);
+PCB_INLINE camv_design_t *camv_obj_parent_design(const camv_any_obj_t *obj);
+PCB_INLINE camv_rtree_box_t *camv_obj_bbox(camv_any_obj_t *obj);
+
+/*** implementation (inlines) ***/
+
+PCB_INLINE camv_layer_t *camv_obj_parent_layer(const camv_any_obj_t *obj)
+{
+ while(obj->proto.parent_obj != NULL) obj = obj->proto.parent_obj;
+ return obj->proto.parent_layer;
+}
+
+PCB_INLINE camv_design_t *camv_obj_parent_design(const camv_any_obj_t *obj)
+{
+ camv_layer_t *ly = camv_obj_parent_layer(obj);
+ if (ly == NULL)
+ return NULL;
+ return ly->parent;
+}
+
+PCB_INLINE camv_rtree_box_t *camv_obj_bbox(camv_any_obj_t *obj)
+{
+ if (!obj->proto.bbox_valid)
+ obj->proto.calls->bbox(obj);
+ assert(obj->proto.bbox_valid);
+ return &obj->proto.bbox;
+}
+
+PCB_INLINE void camv_obj_free(camv_any_obj_t *obj)
+{
+ obj->proto.calls->free_fields(obj);
+ free(obj);
+}
+
+#endif
Index: trunk/src/obj_arc.c
===================================================================
--- trunk/src/obj_arc.c (nonexistent)
+++ trunk/src/obj_arc.c (revision 1)
@@ -0,0 +1,96 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include "obj_arc.h"
+#include "obj_any.h"
+
+#include "hid_inlines.h"
+
+static void camv_arc_free_fields(camv_any_obj_t *obj)
+{
+ /* no dynamic allocation */
+}
+
+static void camv_arc_draw(camv_any_obj_t *obj, pcb_hid_gc_t gc)
+{
+ pcb_hid_set_line_cap(gc, pcb_cap_round);
+ pcb_hid_set_line_width(gc, obj->arc.thick);
+ pcb_gui->draw_arc(gc, obj->arc.cx, obj->arc.cy, obj->arc.r, obj->arc.r, obj->arc.start, obj->arc.delta);
+}
+
+static void camv_arc_bbox(camv_any_obj_t *obj)
+{
+ TODO("real arc bbox");
+ obj->arc.bbox.x1 = obj->arc.cx - obj->arc.r - obj->arc.thick;
+ obj->arc.bbox.x2 = obj->arc.cx + obj->arc.r + obj->arc.thick;
+ obj->arc.bbox.y1 = obj->arc.cy - obj->arc.r - obj->arc.thick;
+ obj->arc.bbox.y2 = obj->arc.cy + obj->arc.r + obj->arc.thick;
+ obj->arc.bbox_valid = 1;
+}
+
+
+static void camv_arc_copy(camv_any_obj_t *dst, const camv_any_obj_t *src)
+{
+ memcpy(&dst->arc, &src->arc, sizeof(camv_arc_t));
+}
+
+static void camv_arc_move(camv_any_obj_t *o, pcb_coord_t dx, pcb_coord_t dy)
+{
+ o->arc.cx += dx;
+ o->arc.cy += dy;
+ if (o->arc.bbox_valid) {
+ o->arc.bbox.x1 += dx; o->arc.bbox.y1 += dy;
+ o->arc.bbox.x2 += dx; o->arc.bbox.y2 += dy;
+ }
+}
+
+static camv_any_obj_t *camv_arc_alloc(void) { return (camv_any_obj_t *)camv_arc_new(); }
+
+static const camv_objcalls_t camv_arc_calls = {
+ camv_arc_alloc,
+ camv_arc_free_fields,
+ camv_arc_draw,
+ camv_arc_bbox,
+ camv_arc_copy,
+ camv_arc_move
+};
+
+void camv_arc_init(camv_arc_t *arc)
+{
+ memset(arc, 0, sizeof(camv_arc_t));
+ arc->type = CAMV_OBJ_ARC;
+ arc->calls = &camv_arc_calls;
+}
+
+camv_arc_t *camv_arc_new(void)
+{
+ camv_arc_t *res = malloc(sizeof(camv_arc_t));
+ camv_arc_init(res);
+ return res;
+}
+
Index: trunk/src/obj_arc.h
===================================================================
--- trunk/src/obj_arc.h (nonexistent)
+++ trunk/src/obj_arc.h (revision 1)
@@ -0,0 +1,43 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_OBJ_ARC_H
+#define CAMV_OBJ_ARC_H
+
+#include "obj_common.h"
+
+typedef struct camv_arc_s {
+ CAMV_ANY_PRIMITIVE_FIELDS;
+ pcb_coord_t cx, cy; /* center */
+ pcb_coord_t r; /* radius */
+ pcb_coord_t thick;
+ pcb_angle_t start, delta;
+} camv_arc_t;
+
+void camv_arc_init(camv_arc_t *arc);
+camv_arc_t *camv_arc_new(void);
+
+#endif
Index: trunk/src/obj_common.h
===================================================================
--- trunk/src/obj_common.h (nonexistent)
+++ trunk/src/obj_common.h (revision 1)
@@ -0,0 +1,65 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_OBJ_COMMON_H
+#define CAMV_OBJ_COMMON_H
+
+#include "global_typedefs.h"
+#include "camv_typedefs.h"
+#include "rtree.h"
+#include "hid.h"
+
+typedef enum camv_objtype_e {
+ CAMV_OBJ_invalid,
+ CAMV_OBJ_ARC,
+ CAMV_OBJ_LINE,
+ CAMV_OBJ_POLY,
+ CAMV_OBJ_GRP,
+ CAMV_OBJ_max
+} camv_objtype_t;
+
+typedef struct camv_objcalls_s {
+ camv_any_obj_t *(*alloc)(void);
+ void (*free_fields)(camv_any_obj_t *obj);
+ void (*draw)(camv_any_obj_t *obj, pcb_hid_gc_t gc);
+ void (*bbox)(camv_any_obj_t *obj);
+ void (*copy)(camv_any_obj_t *dst, const camv_any_obj_t *src);
+ void (*move)(camv_any_obj_t *o, pcb_coord_t dx, pcb_coord_t dy); /* does not do any rtree administration, but bbox is updated if it was originally valid */
+
+} camv_objcalls_t;
+
+#define CAMV_ANY_PRIMITIVE_FIELDS \
+ camv_rtree_box_t bbox; \
+ camv_objtype_t type; \
+ const camv_objcalls_t *calls; \
+ camv_layer_t *parent_layer; \
+ camv_any_obj_t *parent_obj; \
+ unsigned bbox_valid:1;
+
+
+/* NOTE: ->parent_layer is NULL for grp member objects and ->parent_obj is NULL for normal objects */
+
+#endif
Index: trunk/src/obj_grp.c
===================================================================
--- trunk/src/obj_grp.c (nonexistent)
+++ trunk/src/obj_grp.c (revision 1)
@@ -0,0 +1,113 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include "obj_grp.h"
+#include "obj_any.h"
+
+static void camv_grp_free_fields(camv_any_obj_t *obj)
+{
+ pcb_cardinal_t n;
+ camv_any_obj_t *gobj;
+ for(n = 0, gobj = obj->grp.objs; n < obj->grp.len; n++,gobj++)
+ gobj->proto.calls->free_fields(gobj);
+ free(obj->grp.objs);
+ obj->grp.objs = NULL;
+ obj->grp.len = 0;
+}
+
+static void camv_grp_draw(camv_any_obj_t *obj, pcb_hid_gc_t gc)
+{
+ pcb_cardinal_t n;
+ camv_any_obj_t *gobj;
+ for(n = 0, gobj = obj->grp.objs; n < obj->grp.len; n++,gobj++)
+ gobj->proto.calls->draw(gobj, gc);
+}
+
+static void camv_grp_bbox(camv_any_obj_t *obj)
+{
+ pcb_cardinal_t n;
+ camv_any_obj_t *gobj;
+
+ gobj = obj->grp.objs;
+ obj->grp.bbox = *camv_obj_bbox(gobj);
+ for(n = 1, gobj++; n < obj->grp.len; n++,gobj++)
+ camv_rtree_box_bump(&obj->grp.bbox, camv_obj_bbox(gobj));
+ obj->arc.bbox_valid = 1;
+}
+
+static void camv_grp_copy(camv_any_obj_t *dst, const camv_any_obj_t *src)
+{
+ pcb_cardinal_t n;
+ camv_any_obj_t *sobj, *dobj;
+
+ memcpy(&dst->proto, &src->proto, sizeof(src->proto));
+ dst->grp.len = src->grp.len;
+ dst->grp.objs = malloc(sizeof(camv_any_obj_t) * src->grp.len);
+ for(n = 0, sobj = src->grp.objs, dobj = dst->grp.objs; n < src->grp.len; n++,sobj++,dobj++)
+ sobj->proto.calls->copy(dobj, sobj);
+}
+
+static void camv_grp_move(camv_any_obj_t *g, pcb_coord_t dx, pcb_coord_t dy)
+{
+ pcb_cardinal_t n;
+ camv_any_obj_t *o;
+
+ for(n = 0, o = g->grp.objs; n < g->grp.len; n++,o++)
+ o->proto.calls->move(o, dx, dy);
+
+ if (g->grp.bbox_valid) {
+ g->grp.bbox.x1 += dx; g->grp.bbox.y1 += dy;
+ g->grp.bbox.x2 += dx; g->grp.bbox.y2 += dy;
+ }
+}
+
+static camv_any_obj_t *camv_grp_alloc(void) { return (camv_any_obj_t *)camv_grp_new(); }
+
+static const camv_objcalls_t camv_grp_calls = {
+ camv_grp_alloc,
+ camv_grp_free_fields,
+ camv_grp_draw,
+ camv_grp_bbox,
+ camv_grp_copy,
+ camv_grp_move
+};
+
+void camv_grp_init(camv_grp_t *grp)
+{
+ memset(grp, 0, sizeof(camv_grp_t));
+ grp->type = CAMV_OBJ_GRP;
+ grp->calls = &camv_grp_calls;
+}
+
+camv_grp_t *camv_grp_new(void)
+{
+ camv_grp_t *res = malloc(sizeof(camv_grp_t));
+ camv_grp_init(res);
+ return res;
+}
+
Index: trunk/src/obj_grp.h
===================================================================
--- trunk/src/obj_grp.h (nonexistent)
+++ trunk/src/obj_grp.h (revision 1)
@@ -0,0 +1,41 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_OBJ_GRP_H
+#define CAMV_OBJ_GRP_H
+
+#include "obj_common.h"
+
+struct camv_grp_s {
+ CAMV_ANY_PRIMITIVE_FIELDS;
+ pcb_cardinal_t len;
+ camv_any_obj_t *objs; /* allocated to as big as ->len */
+};
+
+void camv_grp_init(camv_grp_t *grp);
+camv_grp_t *camv_grp_new(void);
+
+#endif
Index: trunk/src/obj_line.c
===================================================================
--- trunk/src/obj_line.c (nonexistent)
+++ trunk/src/obj_line.c (revision 1)
@@ -0,0 +1,96 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include "obj_line.h"
+#include "obj_any.h"
+
+#include "hid_inlines.h"
+
+static void camv_line_free_fields(camv_any_obj_t *obj)
+{
+ /* no dynamic allocation */
+}
+
+static void camv_line_draw(camv_any_obj_t *obj, pcb_hid_gc_t gc)
+{
+ pcb_hid_set_line_cap(gc, pcb_cap_round);
+ pcb_hid_set_line_width(gc, obj->line.thick);
+ pcb_gui->draw_line(gc, obj->line.x1, obj->line.y1, obj->line.x2, obj->line.y2);
+}
+
+static void camv_line_bbox(camv_any_obj_t *obj)
+{
+ obj->line.bbox.x1 = MIN(obj->line.x1, obj->line.x2) - obj->line.thick;
+ obj->line.bbox.x2 = MAX(obj->line.x1, obj->line.x2) + obj->line.thick;
+ obj->line.bbox.y1 = MIN(obj->line.y1, obj->line.y2) - obj->line.thick;
+ obj->line.bbox.y2 = MAX(obj->line.y1, obj->line.y2) + obj->line.thick;
+ obj->line.bbox_valid = 1;
+}
+
+static void camv_line_copy(camv_any_obj_t *dst, const camv_any_obj_t *src)
+{
+ memcpy(&dst->line, &src->line, sizeof(camv_line_t));
+}
+
+static void camv_line_move(camv_any_obj_t *o, pcb_coord_t dx, pcb_coord_t dy)
+{
+ o->line.x1 += dx;
+ o->line.x2 += dx;
+ o->line.y1 += dy;
+ o->line.y2 += dy;
+ if (o->line.bbox_valid) {
+ o->line.bbox.x1 += dx; o->line.bbox.y1 += dy;
+ o->line.bbox.x2 += dx; o->line.bbox.y2 += dy;
+ }
+}
+
+static camv_any_obj_t *camv_line_alloc(void) { return (camv_any_obj_t *)camv_line_new(); }
+
+static const camv_objcalls_t camv_line_calls = {
+ camv_line_alloc,
+ camv_line_free_fields,
+ camv_line_draw,
+ camv_line_bbox,
+ camv_line_copy,
+ camv_line_move
+};
+
+void camv_line_init(camv_line_t *line)
+{
+ memset(line, 0, sizeof(camv_line_t));
+ line->type = CAMV_OBJ_LINE;
+ line->calls = &camv_line_calls;
+}
+
+camv_line_t *camv_line_new(void)
+{
+ camv_line_t *res = malloc(sizeof(camv_line_t));
+ camv_line_init(res);
+ return res;
+}
+
Index: trunk/src/obj_line.h
===================================================================
--- trunk/src/obj_line.h (nonexistent)
+++ trunk/src/obj_line.h (revision 1)
@@ -0,0 +1,41 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_OBJ_LINE_H
+#define CAMV_OBJ_LINE_H
+
+#include "obj_common.h"
+
+typedef struct camv_line_s {
+ CAMV_ANY_PRIMITIVE_FIELDS;
+ pcb_coord_t x1, y1, x2, y2;
+ pcb_coord_t thick;
+} camv_line_t;
+
+void camv_line_init(camv_line_t *line);
+camv_line_t *camv_line_new(void);
+
+#endif
Index: trunk/src/obj_poly.c
===================================================================
--- trunk/src/obj_poly.c (nonexistent)
+++ trunk/src/obj_poly.c (revision 1)
@@ -0,0 +1,122 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include "obj_poly.h"
+#include "obj_any.h"
+
+static void camv_poly_free_fields(camv_any_obj_t *obj)
+{
+ vtc0_uninit(&obj->poly.points);
+ obj->poly.x = obj->poly.y = NULL;
+ obj->poly.len = 0;
+}
+
+static void camv_poly_draw(camv_any_obj_t *obj, pcb_hid_gc_t gc)
+{
+ pcb_gui->fill_polygon(gc, obj->poly.len, obj->poly.x, obj->poly.y);
+}
+
+static void camv_poly_bbox(camv_any_obj_t *obj)
+{
+ pcb_cardinal_t n;
+ const pcb_coord_t *x, *y;
+
+ x = obj->poly.x;
+ y = obj->poly.y;
+ obj->poly.bbox.x1 = obj->poly.bbox.x2 = *x;
+ obj->poly.bbox.y1 = obj->poly.bbox.y2 = *y;
+ for(x++, y++, n = 1; n < obj->poly.len; n++,x++,y++) {
+ if (*x < obj->poly.bbox.x1) obj->poly.bbox.x1 = *x;
+ if (*x > obj->poly.bbox.x2) obj->poly.bbox.x2 = *x;
+ if (*y < obj->poly.bbox.y1) obj->poly.bbox.y1 = *y;
+ if (*y > obj->poly.bbox.y2) obj->poly.bbox.y2 = *y;
+ }
+ obj->poly.bbox_valid = 1;
+}
+
+static void camv_poly_copy(camv_any_obj_t *dst, const camv_any_obj_t *src)
+{
+ memcpy(&dst->proto, &src->proto, sizeof(src->proto));
+
+ dst->poly.points.array = NULL;
+ dst->poly.points.alloced = dst->poly.points.used = 0;
+ vtc0_resize(&dst->poly.points, src->poly.points.used);
+ memcpy(dst->poly.points.array, src->poly.points.array, src->poly.points.used * sizeof(pcb_coord_t));
+
+ dst->poly.len = src->poly.len;
+ dst->poly.x = dst->poly.points.array;
+ dst->poly.y = dst->poly.points.array+dst->poly.len;
+}
+
+static void camv_poly_move(camv_any_obj_t *o, pcb_coord_t dx, pcb_coord_t dy)
+{
+ pcb_cardinal_t n;
+
+ for(n = 0; n < o->poly.len; n++) {
+ o->poly.x[n] += dx;
+ o->poly.y[n] += dy;
+ }
+ if (o->poly.bbox_valid) {
+ o->poly.bbox.x1 += dx; o->poly.bbox.y1 += dy;
+ o->poly.bbox.x2 += dx; o->poly.bbox.y2 += dy;
+ }
+}
+
+static camv_any_obj_t *camv_poly_alloc(void) { return (camv_any_obj_t *)camv_poly_new(); }
+
+static const camv_objcalls_t camv_poly_calls = {
+ camv_poly_alloc,
+ camv_poly_free_fields,
+ camv_poly_draw,
+ camv_poly_bbox,
+ camv_poly_copy,
+ camv_poly_move
+};
+
+void camv_poly_init(camv_poly_t *poly)
+{
+ memset(poly, 0, sizeof(camv_poly_t));
+ poly->type = CAMV_OBJ_POLY;
+ poly->calls = &camv_poly_calls;
+}
+
+camv_poly_t *camv_poly_new(void)
+{
+ camv_poly_t *res = malloc(sizeof(camv_poly_t));
+ camv_poly_init(res);
+ return res;
+}
+
+void camv_poly_allocpts(camv_poly_t *poly, pcb_cardinal_t len)
+{
+ poly->len = len;
+ vtc0_resize(&poly->points, len*2);
+ poly->points.used = poly->points.alloced = len*2;
+ poly->x = poly->points.array;
+ poly->y = poly->points.array+len;
+}
Index: trunk/src/obj_poly.h
===================================================================
--- trunk/src/obj_poly.h (nonexistent)
+++ trunk/src/obj_poly.h (revision 1)
@@ -0,0 +1,49 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_OBJ_POLY_H
+#define CAMV_OBJ_POLY_H
+
+#include "obj_common.h"
+#include "vtc0.h"
+
+typedef struct camv_poly_s {
+ CAMV_ANY_PRIMITIVE_FIELDS;
+
+ pcb_coord_t *x;
+ pcb_coord_t *y;
+ pcb_cardinal_t len;
+
+ /* internal */
+ vtc0_t points; /* single allocation for both x and y; first all x coords, then all y coords; as large as ->len*2 */
+} camv_poly_t;
+
+void camv_poly_init(camv_poly_t *poly);
+camv_poly_t *camv_poly_new(void);
+
+void camv_poly_allocpts(camv_poly_t *poly, pcb_cardinal_t len);
+
+#endif
Index: trunk/src/plug_io.c
===================================================================
--- trunk/src/plug_io.c (nonexistent)
+++ trunk/src/plug_io.c (revision 1)
@@ -0,0 +1,100 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "error.h"
+#include "safe_fs.h"
+
+#include "plug_io.h"
+
+
+static vtp0_t camv_io;
+static camv_io_sorted = 0;
+
+static int cmp_io_prio(const void *v1, const void *v2)
+{
+ const camv_io_t *io1 = v1, *io2 = v2;
+
+ if (io1->prio > io2->prio)
+ return 1;
+ return -1;
+}
+
+static void sort_io(void)
+{
+ if (camv_io_sorted)
+ return;
+ qsort(camv_io.array, camv_io.used, sizeof(void *), cmp_io_prio);
+}
+
+void camv_io_reg(camv_io_t *io)
+{
+ vtp0_append(&camv_io, io);
+ camv_io_sorted = 0;
+}
+
+static void post_load(camv_design_t *camv)
+{
+ camv_data_bbox(camv);
+ camv->hidlib.size_x = camv->bbox.x2;
+ camv->hidlib.size_y = camv->bbox.y2;
+}
+
+int camv_io_load(camv_design_t *camv, const char *fn)
+{
+ const camv_io_t *io;
+ int n;
+ FILE *f;
+
+ f = pcb_fopen(&camv->hidlib, fn, "rb");
+ if (f == NULL) {
+ pcb_message(PCB_MSG_ERROR, "Can not open '%s' for read\n", fn);
+ return -1;
+ }
+
+ sort_io();
+
+ for(n = 0; n < camv_io.used; n++) {
+ io = camv_io.array[n];
+ if (io->load == NULL)
+ continue;
+ rewind(f);
+ if ((io->test_load == NULL) || (io->test_load(camv, fn, f) != 0)) {
+ rewind(f);
+ if (io->load(camv, fn, f) == 0) {
+ fclose(f);
+ post_load(camv);
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
Index: trunk/src/plug_io.h
===================================================================
--- trunk/src/plug_io.h (nonexistent)
+++ trunk/src/plug_io.h (revision 1)
@@ -0,0 +1,44 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_RND_PLUG_IO
+#define CAMV_RND_PLUG_IO
+
+#include
+#include "data.h"
+
+typedef struct camv_io_s {
+ const char *name;
+ int prio; /* the higher the better */
+ int (*test_load)(camv_design_t *camv, const char *fn, FILE *f); /* returns non-zero if the file looks good for the plugin */
+ int (*load)(camv_design_t *camv, const char *fn, FILE *f);
+ int (*save_design)(camv_design_t *camv, const char *fn);
+} camv_io_t;
+
+void camv_io_reg(camv_io_t *io);
+int camv_io_load(camv_design_t *camv, const char *fn);
+
+#endif
Index: trunk/src/plug_io_act.c
===================================================================
--- trunk/src/plug_io_act.c (nonexistent)
+++ trunk/src/plug_io_act.c (revision 1)
@@ -0,0 +1,78 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include "actions.h"
+#include "compat_misc.h"
+#include "event.h"
+
+#include "data.h"
+#include "plug_io.h"
+#include "plug_io_act.h"
+
+static const char *plug_io_cookie = "plug_io_act";
+
+static const char pcb_acts_LoadFrom[] = "LoadFrom(Layer|Project,filename[,format])";
+static const char pcb_acth_LoadFrom[] = "Load project or layer data from a file.";
+fgw_error_t pcb_act_LoadFrom(fgw_arg_t *res, int argc, fgw_arg_t *argv)
+{
+ const char *op, *name, *format = NULL;
+
+ PCB_ACT_CONVARG(1, FGW_STR, LoadFrom, op = argv[1].val.str);
+ PCB_ACT_CONVARG(2, FGW_STR, LoadFrom, name = argv[2].val.str);
+ PCB_ACT_MAY_CONVARG(3, FGW_STR, LoadFrom, format = argv[3].val.str);
+
+ if (pcb_strcasecmp(op, "layer") == 0) {
+ if (camv_io_load(&camv, name) != 0) {
+ pcb_message(PCB_MSG_ERROR, "Can not load file '%s'\n", name);
+ PCB_ACT_IRES(-1);
+ return 0;
+ }
+ pcb_event(&camv.hidlib, PCB_EVENT_LAYERS_CHANGED, NULL);
+ }
+ else if (pcb_strcasecmp(op, "project") == 0) {
+ TODO("the actual project load");
+ pcb_message(PCB_MSG_ERROR, "LoadFrom(project,...) not yet implemented\n");
+ }
+ else
+ PCB_ACT_FAIL(LoadFrom);
+
+ PCB_ACT_IRES(0);
+ return 0;
+}
+
+static pcb_action_t camv_plug_io_act_list[] = {
+ {"LoadFrom", pcb_act_LoadFrom, pcb_acth_LoadFrom, pcb_acts_LoadFrom}
+};
+PCB_REGISTER_ACTIONS(camv_plug_io_act_list, plug_io_cookie)
+
+#include "dolists.h"
+
+void camv_plug_io_act_init(void)
+{
+ PCB_REGISTER_ACTIONS(camv_plug_io_act_list, plug_io_cookie);
+}
Index: trunk/src/plug_io_act.h
===================================================================
--- trunk/src/plug_io_act.h (nonexistent)
+++ trunk/src/plug_io_act.h (revision 1)
@@ -0,0 +1,4 @@
+fgw_error_t pcb_act_LoadFrom(fgw_arg_t *res, int argc, fgw_arg_t *argv);
+
+void camv_plug_io_act_init(void);
+
Index: trunk/src/rtree.c
===================================================================
--- trunk/src/rtree.c (nonexistent)
+++ trunk/src/rtree.c (revision 1)
@@ -0,0 +1,38 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "rtree.h"
+
+#include
+#include
+#include
+#include
+
Index: trunk/src/rtree.h
===================================================================
--- trunk/src/rtree.h (nonexistent)
+++ trunk/src/rtree.h (revision 1)
@@ -0,0 +1,44 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#ifndef CAMV_RTREE_H
+#define CAMV_RTREE_H
+
+#include "global_typedefs.h"
+
+typedef long int camv_rtree_cardinal_t;
+typedef pcb_coord_t camv_rtree_coord_t;
+
+/* Instantiate an rtree */
+#define RTR(n) camv_rtree_ ## n
+#define RTRU(n) CAMV_RTREE_ ## n
+#define camv_rtree_privfunc static
+#define camv_rtree_size 6
+#define camv_rtree_stack_max 1024
+
+#include
+
+#endif /* CAMV_RTREE_H */
Index: trunk/src/tedax/a.tdx
===================================================================
--- trunk/src/tedax/a.tdx (nonexistent)
+++ trunk/src/tedax/a.tdx (revision 1)
@@ -0,0 +1,27 @@
+tEDAx v1
+
+begin camv_layer v1 big_blue_rect
+ color #0000ff
+ poly 5 5 60 5 60 60 5 60
+end camv_layer
+
+begin camv_grp v1 arrow1
+ line 10 10 15 10 1
+ line 15 10 13 8 1
+ line 15 10 13 12 1
+end camv_grp
+
+begin camv_layer v1 pcb\ design\ errors
+ color #ff0000
+ arc 14 11 3 0.5 -20 150
+
+ arc 40 40 10 0.2 0 33
+
+ poly 20 20 21 21 22 25
+ unit mil
+ grp arrow1
+ line 350 350 550 550 30
+ polarity clear
+ line 350 340 550 560 5
+end camv_layer
+
Index: trunk/src/tedax/io_tedax.c
===================================================================
--- trunk/src/tedax/io_tedax.c (nonexistent)
+++ trunk/src/tedax/io_tedax.c (revision 1)
@@ -0,0 +1,531 @@
+/*
+ * COPYRIGHT
+ *
+ * camv-rnd - electronics-related CAM viewer
+ * Copyright (C) 2019 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/camv-rnd
+ * lead developer: http://repo.hu/projects/camv-rnd/contact.html
+ * mailing list: camv-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include
+#include
+
+#include "camv_typedefs.h"
+#include "plug_io.h"
+#include "data.h"
+#include "error.h"
+#include "parse.h"
+#include "safe_fs.h"
+#include "compat_misc.h"
+#include "misc_util.h"
+#include "obj_any.h"
+
+typedef struct {
+ camv_design_t *camv;
+ FILE *f;
+ char buf[514];
+ char *argv[16];
+ htsp_t grps; /* group name -> temporary layer */
+} read_ctx_t;
+
+#define coord_conv(dst, argnum, err) \
+do { \
+ pcb_bool succ; \
+ dst = pcb_get_value(argv[argnum], unit, NULL, &succ); \
+ if (!succ) { \
+ pcb_message(PCB_MSG_ERROR, "invalid coordinate value\n"); \
+ err; \
+ } \
+} while(0)
+
+#define double_conv(dst, argnum, err) \
+do { \
+ char *end; \
+ dst = strtod(argv[argnum], &end); \
+ if (*end != '\0') { \
+ pcb_message(PCB_MSG_ERROR, "invalid numeric value\n"); \
+ err; \
+ } \
+} while(0)
+
+static void copy_grp(read_ctx_t *ctx, camv_grp_t *dst, camv_layer_t *src)
+{
+ pcb_cardinal_t n;
+ camv_rtree_it_t it;
+ void *o;
+
+ dst->len = src->objs.size;
+ dst->objs = malloc(sizeof(camv_any_obj_t) * dst->len);
+
+ for(o = camv_rtree_all_first(&it, &src->objs), n = 0; o != NULL; o = camv_rtree_all_next(&it), n++) {
+ camv_any_obj_t *sobj = o;
+ assert(n < dst->len);
+ sobj->proto.calls->copy(&dst->objs[n], sobj);
+ }
+}
+
+static int tdx_parse_layer(read_ctx_t *ctx, camv_layer_t *ly_main, pcb_bool is_grp)
+{
+ char **argv = ctx->argv;
+ int argc;
+ char unit[8];
+ int clearing = 0, has_color = 0;
+ camv_layer_t *ly = ly_main;
+
+ strcpy(unit, "mm");
+
+ for(;;) {
+ if ((argc = tedax_getline(ctx->f, ctx->buf, sizeof(ctx->buf), ctx->argv, sizeof(ctx->argv))) < 0)
+ return -1;
+
+ if (strcmp(argv[0], "end") == 0) {
+ if (!is_grp && (strcmp(argv[1], "camv_layer") == 0))
+ return 0;
+ if (is_grp && (strcmp(argv[1], "camv_grp") == 0))
+ return 0;
+ pcb_message(PCB_MSG_ERROR, "invalid end tag\n");
+ return -1;
+ }
+
+ else if (strcmp(argv[0], "unit") == 0) {
+ if ((strcmp(argv[1], "m") == 0) || (strcmp(argv[1], "mm") == 0) || (strcmp(argv[1], "inch") == 0) || (strcmp(argv[1], "mil") == 0))
+ strcpy(unit, argv[1]);
+ else {
+ pcb_message(PCB_MSG_ERROR, "invalid unit\n");
+ return -1;
+ }
+ }
+
+ else if (strcmp(argv[0], "grp") == 0) {
+ camv_layer_t *gl;
+ camv_grp_t *grp;
+
+ if (argc != 2) {
+ pcb_message(PCB_MSG_ERROR, "invalid number of grp arguments\n");
+ return -1;
+ }
+ gl = htsp_get(&ctx->grps, argv[1]);
+ if (gl == NULL) {
+ pcb_message(PCB_MSG_ERROR, "group '%s' does not exist ref\n", argv[1]);
+ return -1;
+ }
+ grp = camv_grp_new();
+ copy_grp(ctx, grp, gl);
+ camv_obj_add_to_layer(ly, (camv_any_obj_t *)grp);
+ }
+
+ else if (strcmp(argv[0], "color") == 0) {
+ if (argc != 2) {
+ pcb_message(PCB_MSG_ERROR, "invalid number of color arguments\n");
+ return -1;
+ }
+ if (has_color) {
+ pcb_message(PCB_MSG_ERROR, "only one color per layer can be set\n");
+ return -1;
+ }
+ if (is_grp) {
+ pcb_message(PCB_MSG_ERROR, "groups can not change color\n");
+ return -1;
+ }
+ if (pcb_color_load_str(&ly->color, argv[1]) != 0) {
+ pcb_message(PCB_MSG_ERROR, "invalid color string\n");
+ return -1;
+ }
+ has_color = 1;
+ }
+
+ else if (strcmp(argv[0], "polarity") == 0) {
+ int new_clearing;
+ if (argc != 2) {
+ pcb_message(PCB_MSG_ERROR, "invalid number of polarity arguments\n");
+ return -1;
+ }
+ if (is_grp) {
+ pcb_message(PCB_MSG_ERROR, "groups can't change polarity\n");
+ return -1;
+ }
+ if (strcmp(argv[1], "clear") == 0) new_clearing = 1;
+ else if (strcmp(argv[1], "draw") == 0) new_clearing = 0;
+ else {
+ pcb_message(PCB_MSG_ERROR, "invalid polarity value\n");
+ return -1;
+ }
+ if (!has_color) {
+ camv_layer_invent_color(ctx->camv, ly_main);
+ has_color = 1;
+ }
+ if (clearing != new_clearing) {
+ clearing = new_clearing;
+ ly = camv_layer_new();
+ ly->sub = 1;
+ ly->clearing = clearing;
+ ly->color = ly_main->color;
+ camv_layer_append_to_design(ctx->camv, ly);
+ }
+ }
+
+ else if (strcmp(argv[0], "line") == 0) {
+ pcb_coord_t x1, y1, x2, y2, th;
+ camv_line_t *line;
+
+ if (argc != 6) {
+ pcb_message(PCB_MSG_ERROR, "invalid number of line arguments\n");
+ return -1;
+ }
+ coord_conv(x1, 1, return -1);
+ coord_conv(y1, 2, return -1);
+ coord_conv(x2, 3, return -1);
+ coord_conv(y2, 4, return -1);
+ coord_conv(th, 5, return -1);
+ line = camv_line_new();
+ line->x1 = x1; line->y1 = y1;
+ line->x2 = x2; line->y2 = y2;
+ line->thick = th;
+ camv_obj_add_to_layer(ly, (camv_any_obj_t *)line);
+ }
+
+ else if (strcmp(argv[0], "arc") == 0) {
+ pcb_coord_t cx, cy, r, th;
+ double start, delta;
+ camv_arc_t *arc;
+
+ if (argc != 7) {
+ pcb_message(PCB_MSG_ERROR, "invalid number of arc arguments\n");
+ return -1;
+ }
+ coord_conv(cx, 1, return -1);
+ coord_conv(cy, 2, return -1);
+ coord_conv(r, 3, return -1);
+ coord_conv(th, 4, return -1);
+ double_conv(start, 5, return -1);
+ double_conv(delta, 6, return -1);
+ arc = camv_arc_new();
+ arc->cx = cx; arc->cy = cy; arc->r = r;
+ arc->thick = th;
+ arc->start = start - 180;
+ arc->delta = -delta;
+ camv_obj_add_to_layer(ly, (camv_any_obj_t *)arc);
+ }
+
+ else if (strcmp(argv[0], "poly") == 0) {
+ camv_poly_t *poly;
+ int i, n, numcrd;
+
+ numcrd = argc-1;
+ if (argc < 6) {
+ pcb_message(PCB_MSG_ERROR, "too few polygon coords\n");
+ return -1;
+ }
+ if ((numcrd % 2) != 0) {
+ pcb_message(PCB_MSG_ERROR, "need even number of coords in polygon\n");
+ return -1;
+ poly_conv_error:;
+ camv_obj_free((camv_any_obj_t *)poly);
+ return -1;
+ }
+
+ poly = camv_poly_new();
+ camv_poly_allocpts(poly, numcrd/2);
+ for(n = 1, i = 0; n < argc; n += 2, i++) {
+ coord_conv(poly->x[i], n, goto poly_conv_error);
+ coord_conv(poly->y[i], n+1, goto poly_conv_error);
+ }
+ camv_obj_add_to_layer(ly, (camv_any_obj_t *)poly);
+ }
+
+ else {
+ pcb_message(PCB_MSG_ERROR, "Invalid tEDAx line: '%s'\n", argv[0]);
+ return -1;
+ }
+ }
+}
+
+int camv_tdx_load(camv_design_t *camv, const char *fn, FILE *f)
+{
+ read_ctx_t ctx;
+ camv_layer_t *ly;
+ int load_res = 0, found_one = 0;
+ pcb_cardinal_t first_new;
+ long n; /* must be signed */
+ htsp_entry_t *e;
+
+ ctx.camv = camv;
+ ctx.f = f;
+
+ htsp_init(&ctx.grps, strhash, strkeyeq);
+
+ while(tedax_seek_block(ctx.f, "camv_grp", "v1", NULL, 1, ctx.buf, sizeof(ctx.buf), ctx.argv, sizeof(ctx.argv)/sizeof(ctx.argv[0])) >= 0) {
+ if (htsp_has(&ctx.grps, ctx.argv[3])) {
+ pcb_message(PCB_MSG_ERROR, "error: duplicate group: '%s'\n", ctx.argv[3]);
+ load_res = -1;
+ goto error;
+ }
+ ly = camv_layer_new();
+ ly->name = pcb_strdup(ctx.argv[3]);
+ if (tdx_parse_layer(&ctx, ly, 1) != 0) {
+ load_res = -1;
+ goto error;
+ }
+ htsp_set(&ctx.grps, ly->name, ly);
+ }
+
+ rewind(ctx.f);
+
+ first_new = camv->layers.used;
+ while(tedax_seek_block(ctx.f, "camv_layer", "v1", NULL, 1, ctx.buf, sizeof(ctx.buf), ctx.argv, sizeof(ctx.argv)/sizeof(ctx.argv[0])) >= 0) {
+ found_one = 1;
+ ly = camv_layer_new();
+ ly->name = pcb_strdup(ctx.argv[3]);
+ camv_layer_append_to_design(camv, ly);
+ if (tdx_parse_layer(&ctx, ly, 0) != 0) {
+ load_res = -1;
+ /* free all layers created by this load attempt */
+ for(n = camv->layers.used - 1; n >= first_new; n--)
+ camv_layer_destroy(camv->layers.array[n]);
+ goto error;
+ }
+ }
+
+ /* probably not a tedax file */
+ if (!found_one) {
+ load_res = -1;
+ pcb_message(PCB_MSG_ERROR, "error: no camv layer found in '%s'\n", fn);
+ }
+
+ error:;
+ for(e = htsp_first(&ctx.grps); e != NULL; e = htsp_next(&ctx.grps, e))
+ camv_layer_destroy(e->value);
+ htsp_uninit(&ctx.grps);
+ return load_res;
+}
+
+/*** write ***/
+
+typedef struct {
+ camv_design_t *camv;
+ FILE *f;
+ int err;
+} write_ctx_t;
+
+static int tdx_open_write_header(camv_design_t *camv, write_ctx_t *ctx, const char *fn)
+{
+ pcb_printf_slot[4] = "%.06mm";
+ ctx->camv = camv;
+ ctx->f = pcb_fopen((pcb_hidlib_t *)ctx->camv, fn, "w");
+ ctx->err = 0;
+ if (ctx->f == NULL) {
+ pcb_message(PCB_MSG_ERROR, "Can not open '%s' for write\n", fn);
+ return -1;
+ }
+ fprintf(ctx->f, "tEDAx v1\n\n");
+ return 0;
+}
+
+static int tdx_close_write_header(write_ctx_t *ctx)
+{
+ fclose(ctx->f);
+ return ctx->err;
+}
+
+static void tdx_write_obj(write_ctx_t *ctx, const camv_any_obj_t *obj)
+{
+ pcb_cardinal_t n;
+ switch(obj->proto.type) {
+ case CAMV_OBJ_ARC: pcb_fprintf(ctx->f, "\tarc %[4] %[4] %[4] %[4] %f %f\n", obj->arc.cx, obj->arc.cy, obj->arc.r, obj->arc.thick, obj->arc.start+180, -obj->arc.delta); break;
+ case CAMV_OBJ_LINE: pcb_fprintf(ctx->f, "\tline %[4] %[4] %[4] %[4] %[4]\n", obj->line.x1, obj->line.y1, obj->line.x2, obj->line.y2, obj->line.thick); break;
+ case CAMV_OBJ_GRP: fprintf(ctx->f, "\tgrp %p\n", obj); break;
+ case CAMV_OBJ_POLY:
+ fprintf(ctx->f, "\tpoly");
+TODO("split long lines");
+ for(n = 0; n < obj->poly.len; n++)
+ pcb_fprintf(ctx->f, " %[4] %[4]", obj->poly.x[n], obj->poly.y[n]);
+ fprintf(ctx->f, "\n");
+ break;
+ case CAMV_OBJ_max:
+ case CAMV_OBJ_invalid:
+ assert(!"invalid object");
+ break;
+ }
+}
+
+static void tdx_write_grp(write_ctx_t *ctx, const camv_grp_t *grp)
+{
+ pcb_cardinal_t n;
+ fprintf(ctx->f, "begin camv_grp v1 %p\n", grp);
+ for(n = 0; n < grp->len; n++) {
+ assert(grp->objs[n].proto.type != CAMV_OBJ_GRP); /* do not allow group-in-group */
+ tdx_write_obj(ctx, &grp->objs[n]);
+ }
+ fprintf(ctx->f, "end camv_grp\n\n");
+}
+
+static void tdx_write_layer_grps(write_ctx_t *ctx, const camv_layer_t *ly)
+{
+ void *o;
+ camv_rtree_it_t it;
+
+ for(o = camv_rtree_all_first(&it, &ly->objs); o != NULL; o = camv_rtree_all_next(&it)) {
+ camv_any_obj_t *obj = o;
+ if (obj->proto.type != CAMV_OBJ_GRP)
+ continue;
+ tdx_write_grp(ctx, &obj->grp);
+ }
+}
+
+static void tdx_write_layer_head(write_ctx_t *ctx, const camv_layer_t *ly)
+{
+ fprintf(ctx->f, "begin camv_layer v1 ");
+ tedax_fprint_escape(ctx->f, ly->name);
+ fprintf(ctx->f, "\n");
+ fprintf(ctx->f, "\tcolor %s\n", ly->color.str);
+}
+
+static void tdx_write_layer_foot(write_ctx_t *ctx, const camv_layer_t *ly)
+{
+ fprintf(ctx->f, "end camv_layer\n\n");
+}
+
+static void tdx_write_layer(write_ctx_t *ctx, const camv_layer_t *ly)
+{
+ void *o;
+ camv_rtree_it_t it;
+
+ if (ly->clearing)
+ fprintf(ctx->f, "\tpolarity clear\n");
+ else
+ fprintf(ctx->f, "\tpolarity draw\n");
+
+ for(o = camv_rtree_all_first(&it, &ly->objs); o != NULL; o = camv_rtree_all_next(&it))
+ tdx_write_obj(ctx, o);
+}
+
+
+static int camv_tdx_save_sublayer(camv_design_t *camv, const camv_layer_t *ly, const char *fn)
+{
+ write_ctx_t ctx;
+
+ if (tdx_open_write_header(camv, &ctx, fn) != 0)
+ return -1;
+
+ tdx_write_layer_grps(&ctx, ly);
+
+ tdx_write_layer_head(&ctx, ly);
+ tdx_write_layer(&ctx, ly);
+ tdx_write_layer_foot(&ctx, ly);
+
+ return tdx_close_write_header(&ctx);
+}
+
+
+static int camv_tdx_save_layer(camv_design_t *camv, pcb_cardinal_t lid, const char *fn)
+{
+ write_ctx_t ctx;
+ pcb_cardinal_t n;
+ const camv_layer_t *ly;
+
+ if (tdx_open_write_header(camv, &ctx, fn) != 0)
+ return -1;
+
+ for(n = lid; n < camv->layers.used; n++) {
+ ly = camv->layers.array[n];
+ if ((n > lid) && (!ly->sub)) break;
+ tdx_write_layer_grps(&ctx, ly);
+ }
+
+ ly = camv->layers.array[lid];
+ tdx_write_layer_head(&ctx, ly);
+ for(n = lid; n < camv->layers.used; n++) {
+ ly = camv->layers.array[n];
+ if ((n > lid) && (!ly->sub)) break;
+
+ tdx_write_layer(&ctx, ly);
+ }
+ tdx_write_layer_foot(&ctx, ly);
+
+ return tdx_close_write_header(&ctx);
+}
+
+
+static int camv_tdx_save_design(camv_design_t *camv, const char *fn)
+{
+ write_ctx_t ctx;
+ pcb_cardinal_t n;
+ const camv_layer_t *ly;
+
+ if (tdx_open_write_header(camv, &ctx, fn) != 0)
+ return -1;
+
+ for(n = 0; n < camv->layers.used; n++)
+ tdx_write_layer_grps(&ctx, camv->layers.array[n]);
+
+ for(n = 0; n < camv->layers.used; n++) {
+ ly = camv->layers.array[n];
+ if (!ly->sub) {
+ if (n > 0)
+ tdx_write_layer_foot(&ctx, ly);
+ tdx_write_layer_head(&ctx, ly);
+ }
+ tdx_write_layer(&ctx, ly);
+ }
+ tdx_write_layer_foot(&ctx, ly);
+
+ return tdx_close_write_header(&ctx);
+}
+
+static int camv_tdx_test_load(camv_design_t *camv, const char *fn, FILE *f)
+{
+ char *line, line_[1024];
+
+ while((line = fgets(line_, sizeof(line_), f)) != NULL) {
+ while(isspace(*line)) line++;
+ if (*line == '#')
+ continue;
+
+ if (strncmp(line, "tEDAx", 5) != 0)
+ return 0;
+ line += 5;
+ while(isspace(*line)) line++;
+ if (strncmp(line, "v1", 2) != 0)
+ return 0;
+ if (isalnum(line[2]))
+ return 0;
+ return 1;
+ }
+ return 0;
+}
+
+
+static camv_io_t io_tdx = {
+ "tEDAx camv layer", 100,
+ camv_tdx_test_load,
+ camv_tdx_load,
+ camv_tdx_save_design,
+};
+
+
+void camv_tdx_init(void)
+{
+ camv_io_reg(&io_tdx);
+}
Index: trunk/src/tedax/parse.c
===================================================================
--- trunk/src/tedax/parse.c (nonexistent)
+++ trunk/src/tedax/parse.c (revision 1)
@@ -0,0 +1,185 @@
+/*
+ * COPYRIGHT
+ *
+ * pcb-rnd, interactive printed circuit board design
+ *
+ * tedax IO plugin - low level parser, similar to the reference implementation
+ * pcb-rnd Copyright (C) 2017 Tibor 'Igor2' Palinkas
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Contact:
+ * Project page: http://repo.hu/projects/pcb-rnd
+ * lead developer: http://repo.hu/projects/pcb-rnd/contact.html
+ * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
+ */
+
+#include "config.h"
+
+#include
+
+#include "parse.h"
+#include "error.h"
+#include "compat_misc.h"
+
+int tedax_getline(FILE *f, char *buff, int buff_size, char *argv[], int argv_size)
+{
+ int argc;
+
+ for(;;) {
+ char *s, *o;
+
+ if (fgets(buff, buff_size, f) == NULL)
+ return -1;
+
+ s = buff;
+ if (*s == '#') /* comment */
+ continue;
+ ltrim(s);
+ rtrim(s);
+ if (*s == '\0') /* empty line */
+ continue;
+
+ /* argv split */
+ for(argc = 0, o = argv[0] = s; *s != '\0';) {
+ if (*s == '\\') {
+ s++;
+ switch(*s) {
+ case 'r': *o = '\r'; break;
+ case 'n': *o = '\n'; break;
+ case 't': *o = '\t'; break;
+ default: *o = *s;
+ }
+ o++;
+ s++;
+ continue;
+ }
+ if ((argc+1 < argv_size) && ((*s == ' ') || (*s == '\t'))) {
+ *s = '\0';
+ s++;
+ o++;
+ while((*s == ' ') || (*s == '\t'))
+ s++;
+ argc++;
+ argv[argc] = o;
+ }
+ else {
+ *o = *s;
+ s++;
+ o++;
+ }
+ }
+ *o = '\0';
+ return argc+1; /* valid line, split up */
+ }
+
+ return -1; /* can't get here */
+}
+
+int tedax_seek_hdr(FILE *f, char *buff, int buff_size, char *argv[], int argv_size)
+{
+ int argc;
+
+ /* look for the header */
+ if ((argc = tedax_getline(f, buff, buff_size, argv, argv_size)) < 2) {
+ pcb_message(PCB_MSG_ERROR, "Can't find tEDAx header (no line)\n");
+ return -1;
+ }
+
+ if ((argv[1] == NULL) || (pcb_strcasecmp(argv[0], "tEDAx") != 0) || (pcb_strcasecmp(argv[1], "v1") != 0)) {
+ pcb_message(PCB_MSG_ERROR, "Can't find tEDAx header (wrong line)\n");
+ return -1;
+ }
+
+ return argc;
+}
+
+
+int tedax_seek_block(FILE *f, const char *blk_name, const char *blk_ver, const char *blk_id, int silent, char *buff, int buff_size, char *argv[], int argv_size)
+{
+ int argc;
+
+ /* seek block begin */
+ while((argc = tedax_getline(f, buff, buff_size, argv, argv_size)) >= 0)
+ if ((argc > 2) && (strcmp(argv[0], "begin") == 0) && (strcmp(argv[1], blk_name) == 0) && ((blk_ver == NULL) || (strcmp(argv[2], blk_ver) == 0)) && ((blk_id == NULL) || (strcmp(argv[3], blk_id) == 0)))
+ break;
+
+ if (argc < 2) {
+ if (!silent)
+ pcb_message(PCB_MSG_ERROR, "Can't find %s %s block in tEDAx\n", blk_ver, blk_name);
+ return -1;
+ }
+
+ return argc;
+}
+
+void tedax_fprint_escape(FILE *f, const char *val)
+{
+ if ((val == NULL) || (*val == '\0')) {
+ fputc('-', f);
+ return;
+ }
+ for(; *val != '\0'; val++) {
+ switch(*val) {
+ case '\\': fputc('\\', f); fputc('\\', f); break;
+ case '\n': fputc('\\', f); fputc('n', f); break;
+ case '\r': fputc('\\', f); fputc('r', f); break;
+ case '\t': fputc('\\', f); fputc('t', f); break;
+ case ' ': fputc('\\', f); fputc(' ', f); break;
+ default:
+ fputc(*val, f);
+ }
+ }
+}
+
+#define APPEND(c) \
+ do { \
+ if (dstlen == 0) { \
+ res = -1; \
+ goto quit; \
+ } \
+ *d = c; \
+ d++; \
+ dstlen--; \
+ } while(0)
+
+int tedax_strncpy_escape(char *dst, int dstlen, const char *val)
+{
+ int res = 0;
+ char *d = dst;
+
+ assert(dstlen > 2);
+ if ((val == NULL) || (*val == '\0')) {
+ dst[0] = '-';
+ dst[1] = '\0';
+ return 0;
+ }
+ dstlen--; /* one for \0 */
+ for(; *val != '\0'; val++) {
+ switch(*val) {
+ case '\\': APPEND('\\'); APPEND('\\'); break;
+ case '\n': APPEND('\\'); APPEND('n'); break;
+ case '\r': APPEND('\\'); APPEND('r'); break;
+ case '\t': APPEND('\\'); APPEND('t'); break;
+ case ' ': APPEND('\\'); APPEND(' '); break;
+ default:
+ APPEND(*val);
+ }
+ }
+ quit:;
+ *d = '\0';
+ return res;
+}
+
Index: trunk/src/tedax/parse.h
===================================================================
--- trunk/src/tedax/parse.h (nonexistent)
+++ trunk/src/tedax/parse.h (revision 1)
@@ -0,0 +1,29 @@
+#include
+#include
+#include
+
+/* remove leading whitespace */
+#define ltrim(s) while(isspace(*s)) s++
+
+/* remove trailing newline;; trailing backslash is an error */
+#define rtrim(s) \
+ do { \
+ char *end; \
+ for(end = s + strlen(s) - 1; (end >= s) && ((*end == '\r') || (*end == '\n')); end--) \
+ *end = '\0'; \
+ if (*end == '\\') \
+ return -1; \
+ } while(0)
+
+#define null_empty(s) ((s) == NULL ? "" : (s))
+
+int tedax_getline(FILE *f, char *buff, int buff_size, char *argv[], int argv_size);
+
+int tedax_seek_hdr(FILE *f, char *buff, int buff_size, char *argv[], int argv_size);
+int tedax_seek_block(FILE *f, const char *blk_name, const char *blk_ver, const char *blk_id, int silent, char *buff, int buff_size, char *argv[], int argv_size);
+
+
+/* print val with special chars escaped. Prints a single dash if val is NULL or empty. */
+void tedax_fprint_escape(FILE *f, const char *val);
+int tedax_strncpy_escape(char *dst, int dstlen, const char *val);
+