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: +

+ +

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); +