From 235365063fa5b449e0d12b53802ace999e9ca1e7 Mon Sep 17 00:00:00 2001 From: Lukas Cremer Date: Thu, 5 Feb 2026 22:50:36 +0100 Subject: [PATCH] export hpgl load from folder --- output/hpgl/ArsOpifex.hpgl | 2 +- text_to_hpgl.py | 64 ++++++++++++++++++++++---------------- webui/app.py | 59 +++++++++++++++++++++++++++++++++++ webui/static/app.js | 56 +++++++++++++++++++++++++++++++-- webui/static/style.css | 17 ++++++++++ webui/templates/index.html | 5 +++ 6 files changed, 174 insertions(+), 29 deletions(-) diff --git a/output/hpgl/ArsOpifex.hpgl b/output/hpgl/ArsOpifex.hpgl index 5924c08..cc5803b 100755 --- a/output/hpgl/ArsOpifex.hpgl +++ b/output/hpgl/ArsOpifex.hpgl @@ -1 +1 @@ -IN;SP1;PU5174,3108;PD5195,2947;PD5211,2759;PD5222,2555;PD5228,2345;PD5230,2214;PD5232,2175;PD5237,2151;PD5244,2137;PD5255,2133;PD5269,2135;PD5289,2140;PD5303,2147;PD5311,2166;PD5316,2206;PD5321,2278;PD5326,2347;PD5332,2397;PD5343,2435;PD5358,2472;PD5377,2505;PD5402,2540;PD5466,2611;PD5537,2674;PD5572,2698;PD5604,2716;PD5675,2742;PD5748,2758;PD5820,2763;PD5892,2757;PD5961,2741;PD6026,2715;PD6088,2679;PD6143,2633;PD6170,2605;PD6192,2577;PD6210,2548;PD6224,2518;PD6235,2485;PD6242,2450;PD6248,2370;PD6247,2316;PD6242,2277;PD6231,2242;PD6211,2199;PD6191,2163;PD6166,2127;PD6135,2090;PD6098,2053;PD6006,1976;PD5886,1892;PD5776,1817;PD5682,1750;PD5603,1689;PD5536,1632;PD5481,1577;PD5436,1525;PD5399,1472;PD5370,1419;PD5340,1349;PD5320,1282;PD5309,1213;PD5306,1136;PD5308,1078;PD5315,1025;PD5326,975;PD5342,927;PD5364,882;PD5391,839;PD5424,797;PD5462,755;PD5533,693;PD5570,667;PD5609,645;PD5650,626;PD5693,610;PD5739,597;PD5789,587;PD5898,577;PD6023,579;PD6168,592;PD6334,616;PD6375,623;PD6401,497;PD6427,372;PD6467,372;PD6508,372;PD6484,567;PD6464,737;PD6449,907;PD6438,1057;PD6434,1167;PD6434,1241;PD6397,1226;PD6378,1217;PD6366,1205;PD6358,1188;PD6353,1161;PD6345,1044;PD6340,998;PD6328,953;PD6308,910;PD6282,868;PD6249,829;PD6209,793;PD6163,761;PD6112,732;PD6077,717;PD6040,705;PD5966,691;PD5890,689;PD5817,700;PD5748,722;PD5686,755;PD5658,775;PD5633,798;PD5611,824;PD5593,851;PD5579,879;PD5568,908;PD5556,970;PD5557,1033;PD5562,1063;PD5571,1091;PD5585,1119;PD5605,1150;PD5632,1182;PD5665,1216;PD5746,1285;PD5845,1354;PD6068,1498;PD6212,1599;PD6263,1639;PD6304,1677;PD6341,1715;PD6375,1756;PD6406,1799;PD6434,1844;PD6458,1892;PD6478,1942;PD6495,1993;PD6507,2046;PD6516,2100;PD6522,2154;PD6523,2208;PD6520,2262;PD6514,2316;PD6504,2368;PD6490,2419;PD6471,2469;PD6449,2517;PD6423,2562;PD6389,2609;PD6347,2654;PD6300,2697;PD6249,2737;PD6193,2773;PD6134,2804;PD6073,2830;PD6011,2850;PD5946,2863;PD5870,2872;PD5786,2876;PD5698,2876;PD5610,2871;PD5526,2862;PD5450,2849;PD5385,2832;PD5320,2815;PD5287,2970;PD5264,3079;PD5250,3128;PD5234,3136;PD5205,3143;PD5167,3151;PD5174,3108;PU17393,3062;PD17376,3058;PD17366,3045;PD17362,3016;PD17359,2959;PD17356,2861;PD17238,2854;PD16976,2846;PD16512,2838;PD16005,2828;PD15924,2821;PD15909,2817;PD15906,2811;PD15910,2790;PD15916,2782;PD15925,2776;PD15956,2767;PD16007,2761;PD16167,2741;PD16242,2728;PD16250,2524;PD16254,2147;PD16254,1547;PD16250,989;PD16247,809;PD16243,740;PD16200,730;PD16108,716;PD15999,700;PD15940,688;PD15924,681;PD15915,674;PD15910,664;PD15908,653;PD15904,623;PD16523,617;PD16876,611;PD17124,604;PD17282,594;PD17332,587;PD17364,580;PD17373,574;PD17381,560;PD17391,506;PD17399,463;PD17412,435;PD17421,427;PD17433,421;PD17464,417;PD17476,418;PD17482,422;PD17484,429;PD17483,440;PD17452,759;PD17434,973;PD17422,1073;PD17415,1093;PD17406,1099;PD17395,1097;PD17379,1092;PD17339,1079;PD17339,963;PD17339,897;PD17335,860;PD17327,841;PD17310,828;PD17279,812;PD17234,796;PD17110,767;PD16953,743;PD16773,727;PD16654,719;PD16647,791;PD16640,951;PD16632,1235;PD16625,1606;PD16849,1599;PD16990,1593;PD17106,1584;PD17194,1574;PD17251,1562;PD17261,1555;PD17269,1541;PD17284,1489;PD17292,1450;PD17300,1430;PD17314,1423;PD17336,1422;PD17358,1423;PD17369,1427;PD17372,1438;PD17369,1459;PD17327,1757;PD17291,2018;PD17259,2007;PD17226,1995;PD17226,1885;PD17226,1774;PD17190,1762;PD17099,1743;PD16963,1725;PD16803,1712;PD16641,1704;PD16636,1708;PD16633,1720;PD16629,1780;PD16632,2119;PD16647,2633;PD16654,2731;PD16745,2731;PD16911,2725;PD17074,2708;PD17221,2683;PD17283,2668;PD17334,2651;PD17393,2629;PD17426,2491;PD17445,2412;PD17460,2369;PD17467,2358;PD17475,2350;PD17498,2340;PD17540,2330;PD17515,2495;PD17462,2864;PD17443,3009;PD17430,3068;PD17393,3062;PD17393,3062;PU19766,2885;PD19683,2810;PD19596,2727;PD19409,2534;PD19204,2304;PD18978,2035;PD18851,1882;PD18794,1818;PD18783,1827;PD18761,1855;PD18692,1954;PD18497,2259;PD18309,2567;PD18251,2671;PD18236,2702;PD18233,2715;PD18361,2740;PD18485,2760;PD18488,2794;PD18492,2829;PD18085,2828;PD17797,2825;PD17678,2820;PD17688,2784;PD17696,2770;PD17708,2760;PD17728,2753;PD17759,2748;PD17815,2738;PD17865,2723;PD17905,2705;PD17936,2683;PD17996,2617;PD18096,2497;PD18356,2168;PD18598,1850;PD18675,1744;PD18695,1713;PD18701,1699;PD18610,1573;PD18411,1306;PD18059,843;PD18008,782;PD17988,763;PD17967,748;PD17945,737;PD17917,729;PD17833,711;PD17787,698;PD17773,691;PD17768,684;PD17762,649;PD17761,641;PD17767,636;PD17785,632;PD17821,629;PD17968,626;PD18253,626;PD18750,627;PD18737,667;PD18720,699;PD18590,719;PD18514,734;PD18477,743;PD18491,774;PD18537,848;PD18685,1072;PD18843,1301;PD18902,1381;PD18935,1421;PD18941,1422;PD18949,1418;PD18978,1388;PD19102,1219;PD19217,1051;PD19314,905;PD19380,799;PD19399,765;PD19405,748;PD19397,742;PD19375,734;PD19298,716;PD19211,697;PD19195,687;PD19191,676;PD19185,641;PD19187,637;PD19197,634;PD19252,629;PD19552,626;PD19924,626;PD19924,662;PD19924,698;PD19818,722;PD19711,746;PD19611,855;PD19386,1112;PD19103,1446;PD19022,1544;PD19114,1672;PD19420,2105;PD19819,2666;PD20003,2928;PD19991,2935;PD19961,2945;PD19902,2959;PD19882,2961;PD19864,2958;PD19846,2950;PD19826,2936;PD19766,2885;PD19766,2885;PU4863,2871;PD4799,2818;PD4715,2741;PD4503,2529;PD4253,2262;PD3992,1966;PD3843,1794;PD3697,1801;PD3546,1811;PD3546,1954;PD3552,2262;PD3561,2571;PD3568,2714;PD3619,2724;PD3731,2739;PD3890,2759;PD3899,2794;PD3906,2827;PD2838,2827;PD2224,2827;PD1907,2825;PD1830,2822;PD1791,2818;PD1777,2812;PD1777,2805;PD1783,2768;PD1786,2762;PD1793,2758;PD1818,2754;PD1969,2737;PD2056,2724;PD2097,2715;PD2062,2606;PD1978,2360;PD1818,1910;PD1790,1843;PD1774,1813;PD1738,1811;PD1656,1813;PD1417,1824;PD1178,1841;PD1098,1849;PD1064,1855;PD1046,1899;PD1016,1999;PD940,2290;PD872,2578;PD853,2675;PD849,2704;PD850,2716;PD986,2740;PD1092,2759;PD1112,2768;PD1117,2778;PD1123,2812;PD1121,2817;PD1109,2820;PD1046,2824;PD705,2827;PD281,2827;PD284,2794;PD287,2761;PD417,2740;PD513,2722;PD545,2713;PD560,2706;PD578,2676;PD608,2610;PD710,2365;PD870,1956;PD1094,1371;PD1304,817;PD1328,745;PD1329,735;PD1327,733;PD1210,716;PD1144,703;PD1105,691;PD1094,683;PD1088,674;PD1083,649;PD1085,641;PD1092,636;PD1111,632;PD1146,629;PD1289,626;PD1563,626;PD2043,626;PD2036,660;PD2027,696;PD1913,716;PD1798,738;PD1822,820;PD1890,1022;PD2085,1574;PD2201,1887;PD2311,2173;PD2408,2411;PD2483,2581;PD2548,2718;PD2684,2738;PD2757,2749;PD2799,2758;PD2819,2768;PD2825,2781;PD2830,2805;PD2831,2781;PD2835,2768;PD2846,2760;PD2871,2755;PD2915,2750;PD3083,2730;PD3170,2718;PD3177,2592;PD3181,2245;PD3181,1617;PD3177,1014;PD3172,741;PD3120,732;PD3005,719;PD2839,698;PD2831,660;PD2827,626;PD3392,627;PD3776,630;PD4034,640;PD4129,649;PD4209,660;PD4279,675;PD4345,694;PD4418,722;PD4482,755;PD4536,793;PD4581,837;PD4616,886;PD4641,940;PD4657,998;PD4662,1061;PD4655,1128;PD4635,1199;PD4604,1271;PD4561,1343;PD4509,1413;PD4447,1481;PD4378,1544;PD4303,1601;PD4250,1642;PD4239,1656;PD4238,1667;PD4278,1739;PD4365,1879;PD4586,2221;PD4701,2390;PD4802,2533;PD4898,2661;PD4996,2784;PD5090,2899;PD5019,2911;PD4942,2923;PD4863,2871;PD4863,2871;PU1658,1442;PD1501,987;PD1454,854;PD1434,802;PD1281,1221;PD1122,1663;PD1115,1692;PD1277,1696;PD1594,1702;PD1749,1704;PD1658,1442;PU3785,1675;PD3871,1655;PD3943,1631;PD4007,1599;PD4067,1559;PD4114,1519;PD4155,1477;PD4190,1431;PD4219,1383;PD4242,1332;PD4258,1278;PD4268,1222;PD4271,1163;PD4271,1117;PD4266,1081;PD4257,1049;PD4241,1013;PD4205,955;PD4158,903;PD4100,857;PD4032,817;PD3955,783;PD3869,757;PD3775,738;PD3674,726;PD3569,719;PD3563,768;PD3556,934;PD3550,1261;PD3543,1705;PD3620,1698;PD3700,1688;PD3785,1675;PD3785,1675;PU8641,2866;PD8541,2847;PD8445,2822;PD8354,2791;PD8268,2753;PD8187,2710;PD8110,2660;PD8037,2603;PD7969,2540;PD7913,2481;PD7863,2421;PD7819,2361;PD7781,2300;PD7749,2237;PD7721,2172;PD7698,2105;PD7680,2034;PD7672,1983;PD7666,1921;PD7661,1779;PD7665,1637;PD7671,1576;PD7680,1526;PD7696,1463;PD7716,1400;PD7740,1339;PD7767,1279;PD7798,1220;PD7832,1164;PD7869,1109;PD7909,1057;PD7952,1006;PD7998,958;PD8046,913;PD8097,870;PD8151,830;PD8206,793;PD8264,759;PD8324,728;PD8413,688;PD8495,657;PD8581,631;PD8682,607;PD8752,596;PD8839,587;PD9041,579;PD9240,584;PD9325,591;PD9392,601;PD9490,626;PD9586,657;PD9677,695;PD9764,737;PD9844,785;PD9918,837;PD9983,892;PD10039,951;PD10108,1041;PD10165,1135;PD10211,1234;PD10246,1337;PD10269,1446;PD10282,1559;PD10283,1678;PD10272,1801;PD10256,1902;PD10232,1998;PD10201,2090;PD10163,2179;PD10117,2263;PD10064,2344;PD10003,2421;PD9935,2495;PD9864,2561;PD9792,2620;PD9716,2672;PD9637,2719;PD9553,2759;PD9464,2794;PD9369,2825;PD9268,2850;PD9217,2858;PD9143,2864;PD8958,2873;PD8771,2874;PD8696,2871;PD8641,2866;PD8641,2866;PU9213,2730;PD9270,2717;PD9324,2699;PD9377,2678;PD9428,2653;PD9477,2624;PD9524,2592;PD9569,2557;PD9612,2518;PD9652,2476;PD9689,2431;PD9724,2383;PD9757,2333;PD9786,2279;PD9812,2223;PD9836,2164;PD9856,2104;PD9867,2057;PD9876,2002;PD9886,1875;PD9885,1742;PD9881,1680;PD9873,1622;PD9847,1501;PD9810,1387;PD9765,1280;PD9711,1180;PD9649,1089;PD9579,1006;PD9503,933;PD9421,869;PD9334,814;PD9242,771;PD9145,738;PD9046,716;PD8943,706;PD8839,709;PD8733,724;PD8626,752;PD8574,771;PD8523,792;PD8475,817;PD8429,844;PD8385,874;PD8343,906;PD8303,941;PD8266,979;PD8198,1061;PD8141,1152;PD8094,1252;PD8059,1360;PD8047,1416;PD8038,1480;PD8033,1550;PD8031,1623;PD8033,1696;PD8038,1767;PD8046,1833;PD8058,1890;PD8079,1962;PD8105,2032;PD8135,2101;PD8169,2168;PD8207,2233;PD8249,2295;PD8294,2354;PD8342,2408;PD8406,2471;PD8472,2528;PD8542,2578;PD8614,2622;PD8688,2659;PD8765,2690;PD8844,2714;PD8925,2731;PD8995,2739;PD9074,2741;PD9151,2738;PD9214,2730;PD9213,2730;PU10538,2812;PD10543,2778;PD10545,2772;PD10549,2767;PD10573,2758;PD10710,2738;PD10881,2713;PD10885,2645;PD10888,2468;PD10891,1921;PD10892,1333;PD10888,966;PD10878,783;PD10871,750;PD10866,743;PD10861,739;PD10698,718;PD10548,697;PD10536,655;PD10529,618;PD11058,624;PD11498,632;PD11626,639;PD11712,647;PD11818,666;PD11913,689;PD11997,718;PD12069,751;PD12132,791;PD12184,836;PD12227,887;PD12262,945;PD12282,989;PD12293,1024;PD12297,1063;PD12298,1118;PD12294,1185;PD12283,1250;PD12266,1314;PD12242,1375;PD12212,1433;PD12176,1490;PD12134,1543;PD12086,1594;PD12033,1642;PD11974,1687;PD11910,1728;PD11840,1767;PD11765,1802;PD11685,1833;PD11601,1861;PD11511,1885;PD11445,1899;PD11416,1903;PD11421,1858;PD11427,1834;PD11439,1818;PD11462,1805;PD11503,1790;PD11590,1754;PD11667,1709;PD11734,1656;PD11790,1595;PD11837,1527;PD11873,1450;PD11899,1366;PD11914,1275;PD11916,1198;PD11907,1124;PD11887,1053;PD11858,987;PD11820,927;PD11774,874;PD11720,830;PD11658,795;PD11597,774;PD11518,754;PD11431,739;PD11344,730;PD11269,725;PD11262,918;PD11257,1214;PD11255,1646;PD11257,2096;PD11262,2446;PD11269,2718;PD11471,2738;PD11618,2756;PD11658,2764;PD11672,2770;PD11679,2805;PD11679,2812;PD11672,2818;PD11651,2822;PD11610,2824;PD11439,2827;PD11108,2827;PD10643,2824;PD10558,2820;PD10541,2817;PD10538,2812;PD10538,2812;PU12536,2812;PD12541,2778;PD12543,2772;PD12547,2767;PD12571,2758;PD12708,2738;PD12827,2723;PD12880,2713;PD12884,2422;PD12886,1731;PD12883,949;PD12878,793;PD12875,758;PD12871,746;PD12817,734;PD12708,718;PD12600,702;PD12551,690;PD12538,654;PD12531,626;PD13078,626;PD13624,626;PD13618,654;PD13611,677;PD13603,691;PD13552,704;PD13441,721;PD13329,737;PD13278,749;PD13275,836;PD13272,1059;PD13270,1731;PD13271,2404;PD13273,2626;PD13276,2713;PD13328,2724;PD13445,2740;PD13607,2760;PD13614,2794;PD13621,2827;PD13076,2827;PD12635,2824;PD12555,2820;PD12539,2817;PD12536,2812;PD12536,2812;PU13913,2812;PD13919,2777;PD13923,2766;PD13942,2758;PD14052,2744;PD14173,2731;PD14209,2724;PD14232,2714;PD14246,2699;PD14253,2676;PD14259,2601;PD14265,2296;PD14267,1760;PD14266,1215;PD14261,889;PD14254,735;PD14168,723;PD14001,704;PD13956,699;PD13931,693;PD13921,685;PD13919,670;PD13913,630;PD13918,626;PD13941,622;PD14055,618;PD14680,618;PD15452,622;PD15472,510;PD15491,397;PD15531,391;PD15574,386;PD15566,451;PD15545,668;PD15526,972;PD15519,1137;PD15483,1126;PD15445,1111;PD15432,992;PD15427,931;PD15421,893;PD15412,870;PD15398,856;PD15364,835;PD15312,816;PD15245,797;PD15163,780;PD15070,764;PD14965,751;PD14729,730;PD14695,729;PD14675,730;PD14664,737;PD14659,749;PD14652,888;PD14645,1189;PD14638,1606;PD14834,1598;PD15005,1589;PD15143,1579;PD15238,1567;PD15267,1562;PD15281,1556;PD15296,1523;PD15313,1460;PD15332,1394;PD15342,1380;PD15353,1377;PD15393,1369;PD15403,1367;PD15407,1371;PD15405,1412;PD15392,1524;PD15379,1691;PD15368,1861;PD15364,1979;PD15364,2079;PD15328,2072;PD15288,2061;PD15277,1935;PD15270,1842;PD15261,1793;PD15245,1780;PD15213,1767;PD15165,1756;PD15104,1744;PD14943,1725;PD14740,1711;PD14641,1707;PD14642,2019;PD14645,2291;PD14651,2506;PD14659,2650;PD14664,2690;PD14670,2708;PD14687,2714;PD14726,2722;PD14844,2740;PD15007,2760;PD15014,2794;PD15021,2827;PD14464,2827;PD14015,2824;PD13932,2820;PD13916,2817;PD13913,2812;PD13913,2812;PU; +IN;SP1;PU5174,-3108;PD5195,-2947;PD5211,-2759;PD5222,-2555;PD5228,-2345;PD5230,-2214;PD5232,-2175;PD5237,-2151;PD5244,-2137;PD5255,-2133;PD5269,-2135;PD5289,-2140;PD5303,-2147;PD5311,-2166;PD5316,-2206;PD5321,-2278;PD5326,-2347;PD5332,-2397;PD5343,-2435;PD5358,-2472;PD5377,-2505;PD5402,-2540;PD5466,-2611;PD5537,-2674;PD5572,-2698;PD5604,-2716;PD5675,-2742;PD5748,-2758;PD5820,-2763;PD5892,-2757;PD5961,-2741;PD6026,-2715;PD6088,-2679;PD6143,-2633;PD6170,-2605;PD6192,-2577;PD6210,-2548;PD6224,-2518;PD6235,-2485;PD6242,-2450;PD6248,-2370;PD6247,-2316;PD6242,-2277;PD6231,-2242;PD6211,-2199;PD6191,-2163;PD6166,-2127;PD6135,-2090;PD6098,-2053;PD6006,-1976;PD5886,-1892;PD5776,-1817;PD5682,-1750;PD5603,-1689;PD5536,-1632;PD5481,-1577;PD5436,-1525;PD5399,-1472;PD5370,-1419;PD5340,-1349;PD5320,-1282;PD5309,-1213;PD5306,-1136;PD5308,-1078;PD5315,-1025;PD5326,-975;PD5342,-927;PD5364,-882;PD5391,-839;PD5424,-797;PD5462,-755;PD5533,-693;PD5570,-667;PD5609,-645;PD5650,-626;PD5693,-610;PD5739,-597;PD5789,-587;PD5898,-577;PD6023,-579;PD6168,-592;PD6334,-616;PD6375,-623;PD6401,-497;PD6427,-372;PD6467,-372;PD6508,-372;PD6484,-567;PD6464,-737;PD6449,-907;PD6438,-1057;PD6434,-1167;PD6434,-1241;PD6397,-1226;PD6378,-1217;PD6366,-1205;PD6358,-1188;PD6353,-1161;PD6345,-1044;PD6340,-998;PD6328,-953;PD6308,-910;PD6282,-868;PD6249,-829;PD6209,-793;PD6163,-761;PD6112,-732;PD6077,-717;PD6040,-705;PD5966,-691;PD5890,-689;PD5817,-700;PD5748,-722;PD5686,-755;PD5658,-775;PD5633,-798;PD5611,-824;PD5593,-851;PD5579,-879;PD5568,-908;PD5556,-970;PD5557,-1033;PD5562,-1063;PD5571,-1091;PD5585,-1119;PD5605,-1150;PD5632,-1182;PD5665,-1216;PD5746,-1285;PD5845,-1354;PD6068,-1498;PD6212,-1599;PD6263,-1639;PD6304,-1677;PD6341,-1715;PD6375,-1756;PD6406,-1799;PD6434,-1844;PD6458,-1892;PD6478,-1942;PD6495,-1993;PD6507,-2046;PD6516,-2100;PD6522,-2154;PD6523,-2208;PD6520,-2262;PD6514,-2316;PD6504,-2368;PD6490,-2419;PD6471,-2469;PD6449,-2517;PD6423,-2562;PD6389,-2609;PD6347,-2654;PD6300,-2697;PD6249,-2737;PD6193,-2773;PD6134,-2804;PD6073,-2830;PD6011,-2850;PD5946,-2863;PD5870,-2872;PD5786,-2876;PD5698,-2876;PD5610,-2871;PD5526,-2862;PD5450,-2849;PD5385,-2832;PD5320,-2815;PD5287,-2970;PD5264,-3079;PD5250,-3128;PD5234,-3136;PD5205,-3143;PD5167,-3151;PD5174,-3108;PU17393,-3062;PD17376,-3058;PD17366,-3045;PD17362,-3016;PD17359,-2959;PD17356,-2861;PD17238,-2854;PD16976,-2846;PD16512,-2838;PD16005,-2828;PD15924,-2821;PD15909,-2817;PD15906,-2811;PD15910,-2790;PD15916,-2782;PD15925,-2776;PD15956,-2767;PD16007,-2761;PD16167,-2741;PD16242,-2728;PD16250,-2524;PD16254,-2147;PD16254,-1547;PD16250,-989;PD16247,-809;PD16243,-740;PD16200,-730;PD16108,-716;PD15999,-700;PD15940,-688;PD15924,-681;PD15915,-674;PD15910,-664;PD15908,-653;PD15904,-623;PD16523,-617;PD16876,-611;PD17124,-604;PD17282,-594;PD17332,-587;PD17364,-580;PD17373,-574;PD17381,-560;PD17391,-506;PD17399,-463;PD17412,-435;PD17421,-427;PD17433,-421;PD17464,-417;PD17476,-418;PD17482,-422;PD17484,-429;PD17483,-440;PD17452,-759;PD17434,-973;PD17422,-1073;PD17415,-1093;PD17406,-1099;PD17395,-1097;PD17379,-1092;PD17339,-1079;PD17339,-963;PD17339,-897;PD17335,-860;PD17327,-841;PD17310,-828;PD17279,-812;PD17234,-796;PD17110,-767;PD16953,-743;PD16773,-727;PD16654,-719;PD16647,-791;PD16640,-951;PD16632,-1235;PD16625,-1606;PD16849,-1599;PD16990,-1593;PD17106,-1584;PD17194,-1574;PD17251,-1562;PD17261,-1555;PD17269,-1541;PD17284,-1489;PD17292,-1450;PD17300,-1430;PD17314,-1423;PD17336,-1422;PD17358,-1423;PD17369,-1427;PD17372,-1438;PD17369,-1459;PD17327,-1757;PD17291,-2018;PD17259,-2007;PD17226,-1995;PD17226,-1885;PD17226,-1774;PD17190,-1762;PD17099,-1743;PD16963,-1725;PD16803,-1712;PD16641,-1704;PD16636,-1708;PD16633,-1720;PD16629,-1780;PD16632,-2119;PD16647,-2633;PD16654,-2731;PD16745,-2731;PD16911,-2725;PD17074,-2708;PD17221,-2683;PD17283,-2668;PD17334,-2651;PD17393,-2629;PD17426,-2491;PD17445,-2412;PD17460,-2369;PD17467,-2358;PD17475,-2350;PD17498,-2340;PD17540,-2330;PD17515,-2495;PD17462,-2864;PD17443,-3009;PD17430,-3068;PD17393,-3062;PD17393,-3062;PU19766,-2885;PD19683,-2810;PD19596,-2727;PD19409,-2534;PD19204,-2304;PD18978,-2035;PD18851,-1882;PD18794,-1818;PD18783,-1827;PD18761,-1855;PD18692,-1954;PD18497,-2259;PD18309,-2567;PD18251,-2671;PD18236,-2702;PD18233,-2715;PD18361,-2740;PD18485,-2760;PD18488,-2794;PD18492,-2829;PD18085,-2828;PD17797,-2825;PD17678,-2820;PD17688,-2784;PD17696,-2770;PD17708,-2760;PD17728,-2753;PD17759,-2748;PD17815,-2738;PD17865,-2723;PD17905,-2705;PD17936,-2683;PD17996,-2617;PD18096,-2497;PD18356,-2168;PD18598,-1850;PD18675,-1744;PD18695,-1713;PD18701,-1699;PD18610,-1573;PD18411,-1306;PD18059,-843;PD18008,-782;PD17988,-763;PD17967,-748;PD17945,-737;PD17917,-729;PD17833,-711;PD17787,-698;PD17773,-691;PD17768,-684;PD17762,-649;PD17761,-641;PD17767,-636;PD17785,-632;PD17821,-629;PD17968,-626;PD18253,-626;PD18750,-627;PD18737,-667;PD18720,-699;PD18590,-719;PD18514,-734;PD18477,-743;PD18491,-774;PD18537,-848;PD18685,-1072;PD18843,-1301;PD18902,-1381;PD18935,-1421;PD18941,-1422;PD18949,-1418;PD18978,-1388;PD19102,-1219;PD19217,-1051;PD19314,-905;PD19380,-799;PD19399,-765;PD19405,-748;PD19397,-742;PD19375,-734;PD19298,-716;PD19211,-697;PD19195,-687;PD19191,-676;PD19185,-641;PD19187,-637;PD19197,-634;PD19252,-629;PD19552,-626;PD19924,-626;PD19924,-662;PD19924,-698;PD19818,-722;PD19711,-746;PD19611,-855;PD19386,-1112;PD19103,-1446;PD19022,-1544;PD19114,-1672;PD19420,-2105;PD19819,-2666;PD20003,-2928;PD19991,-2935;PD19961,-2945;PD19902,-2959;PD19882,-2961;PD19864,-2958;PD19846,-2950;PD19826,-2936;PD19766,-2885;PD19766,-2885;PU4863,-2871;PD4799,-2818;PD4715,-2741;PD4503,-2529;PD4253,-2262;PD3992,-1966;PD3843,-1794;PD3697,-1801;PD3546,-1811;PD3546,-1954;PD3552,-2262;PD3561,-2571;PD3568,-2714;PD3619,-2724;PD3731,-2739;PD3890,-2759;PD3899,-2794;PD3906,-2827;PD2838,-2827;PD2224,-2827;PD1907,-2825;PD1830,-2822;PD1791,-2818;PD1777,-2812;PD1777,-2805;PD1783,-2768;PD1786,-2762;PD1793,-2758;PD1818,-2754;PD1969,-2737;PD2056,-2724;PD2097,-2715;PD2062,-2606;PD1978,-2360;PD1818,-1910;PD1790,-1843;PD1774,-1813;PD1738,-1811;PD1656,-1813;PD1417,-1824;PD1178,-1841;PD1098,-1849;PD1064,-1855;PD1046,-1899;PD1016,-1999;PD940,-2290;PD872,-2578;PD853,-2675;PD849,-2704;PD850,-2716;PD986,-2740;PD1092,-2759;PD1112,-2768;PD1117,-2778;PD1123,-2812;PD1121,-2817;PD1109,-2820;PD1046,-2824;PD705,-2827;PD281,-2827;PD284,-2794;PD287,-2761;PD417,-2740;PD513,-2722;PD545,-2713;PD560,-2706;PD578,-2676;PD608,-2610;PD710,-2365;PD870,-1956;PD1094,-1371;PD1304,-817;PD1328,-745;PD1329,-735;PD1327,-733;PD1210,-716;PD1144,-703;PD1105,-691;PD1094,-683;PD1088,-674;PD1083,-649;PD1085,-641;PD1092,-636;PD1111,-632;PD1146,-629;PD1289,-626;PD1563,-626;PD2043,-626;PD2036,-660;PD2027,-696;PD1913,-716;PD1798,-738;PD1822,-820;PD1890,-1022;PD2085,-1574;PD2201,-1887;PD2311,-2173;PD2408,-2411;PD2483,-2581;PD2548,-2718;PD2684,-2738;PD2757,-2749;PD2799,-2758;PD2819,-2768;PD2825,-2781;PD2830,-2805;PD2831,-2781;PD2835,-2768;PD2846,-2760;PD2871,-2755;PD2915,-2750;PD3083,-2730;PD3170,-2718;PD3177,-2592;PD3181,-2245;PD3181,-1617;PD3177,-1014;PD3172,-741;PD3120,-732;PD3005,-719;PD2839,-698;PD2831,-660;PD2827,-626;PD3392,-627;PD3776,-630;PD4034,-640;PD4129,-649;PD4209,-660;PD4279,-675;PD4345,-694;PD4418,-722;PD4482,-755;PD4536,-793;PD4581,-837;PD4616,-886;PD4641,-940;PD4657,-998;PD4662,-1061;PD4655,-1128;PD4635,-1199;PD4604,-1271;PD4561,-1343;PD4509,-1413;PD4447,-1481;PD4378,-1544;PD4303,-1601;PD4250,-1642;PD4239,-1656;PD4238,-1667;PD4278,-1739;PD4365,-1879;PD4586,-2221;PD4701,-2390;PD4802,-2533;PD4898,-2661;PD4996,-2784;PD5090,-2899;PD5019,-2911;PD4942,-2923;PD4863,-2871;PD4863,-2871;PU1658,-1442;PD1501,-987;PD1454,-854;PD1434,-802;PD1281,-1221;PD1122,-1663;PD1115,-1692;PD1277,-1696;PD1594,-1702;PD1749,-1704;PD1658,-1442;PU3785,-1675;PD3871,-1655;PD3943,-1631;PD4007,-1599;PD4067,-1559;PD4114,-1519;PD4155,-1477;PD4190,-1431;PD4219,-1383;PD4242,-1332;PD4258,-1278;PD4268,-1222;PD4271,-1163;PD4271,-1117;PD4266,-1081;PD4257,-1049;PD4241,-1013;PD4205,-955;PD4158,-903;PD4100,-857;PD4032,-817;PD3955,-783;PD3869,-757;PD3775,-738;PD3674,-726;PD3569,-719;PD3563,-768;PD3556,-934;PD3550,-1261;PD3543,-1705;PD3620,-1698;PD3700,-1688;PD3785,-1675;PD3785,-1675;PU8641,-2866;PD8541,-2847;PD8445,-2822;PD8354,-2791;PD8268,-2753;PD8187,-2710;PD8110,-2660;PD8037,-2603;PD7969,-2540;PD7913,-2481;PD7863,-2421;PD7819,-2361;PD7781,-2300;PD7749,-2237;PD7721,-2172;PD7698,-2105;PD7680,-2034;PD7672,-1983;PD7666,-1921;PD7661,-1779;PD7665,-1637;PD7671,-1576;PD7680,-1526;PD7696,-1463;PD7716,-1400;PD7740,-1339;PD7767,-1279;PD7798,-1220;PD7832,-1164;PD7869,-1109;PD7909,-1057;PD7952,-1006;PD7998,-958;PD8046,-913;PD8097,-870;PD8151,-830;PD8206,-793;PD8264,-759;PD8324,-728;PD8413,-688;PD8495,-657;PD8581,-631;PD8682,-607;PD8752,-596;PD8839,-587;PD9041,-579;PD9240,-584;PD9325,-591;PD9392,-601;PD9490,-626;PD9586,-657;PD9677,-695;PD9764,-737;PD9844,-785;PD9918,-837;PD9983,-892;PD10039,-951;PD10108,-1041;PD10165,-1135;PD10211,-1234;PD10246,-1337;PD10269,-1446;PD10282,-1559;PD10283,-1678;PD10272,-1801;PD10256,-1902;PD10232,-1998;PD10201,-2090;PD10163,-2179;PD10117,-2263;PD10064,-2344;PD10003,-2421;PD9935,-2495;PD9864,-2561;PD9792,-2620;PD9716,-2672;PD9637,-2719;PD9553,-2759;PD9464,-2794;PD9369,-2825;PD9268,-2850;PD9217,-2858;PD9143,-2864;PD8958,-2873;PD8771,-2874;PD8696,-2871;PD8641,-2866;PD8641,-2866;PU9213,-2730;PD9270,-2717;PD9324,-2699;PD9377,-2678;PD9428,-2653;PD9477,-2624;PD9524,-2592;PD9569,-2557;PD9612,-2518;PD9652,-2476;PD9689,-2431;PD9724,-2383;PD9757,-2333;PD9786,-2279;PD9812,-2223;PD9836,-2164;PD9856,-2104;PD9867,-2057;PD9876,-2002;PD9886,-1875;PD9885,-1742;PD9881,-1680;PD9873,-1622;PD9847,-1501;PD9810,-1387;PD9765,-1280;PD9711,-1180;PD9649,-1089;PD9579,-1006;PD9503,-933;PD9421,-869;PD9334,-814;PD9242,-771;PD9145,-738;PD9046,-716;PD8943,-706;PD8839,-709;PD8733,-724;PD8626,-752;PD8574,-771;PD8523,-792;PD8475,-817;PD8429,-844;PD8385,-874;PD8343,-906;PD8303,-941;PD8266,-979;PD8198,-1061;PD8141,-1152;PD8094,-1252;PD8059,-1360;PD8047,-1416;PD8038,-1480;PD8033,-1550;PD8031,-1623;PD8033,-1696;PD8038,-1767;PD8046,-1833;PD8058,-1890;PD8079,-1962;PD8105,-2032;PD8135,-2101;PD8169,-2168;PD8207,-2233;PD8249,-2295;PD8294,-2354;PD8342,-2408;PD8406,-2471;PD8472,-2528;PD8542,-2578;PD8614,-2622;PD8688,-2659;PD8765,-2690;PD8844,-2714;PD8925,-2731;PD8995,-2739;PD9074,-2741;PD9151,-2738;PD9214,-2730;PD9213,-2730;PU10538,-2812;PD10543,-2778;PD10545,-2772;PD10549,-2767;PD10573,-2758;PD10710,-2738;PD10881,-2713;PD10885,-2645;PD10888,-2468;PD10891,-1921;PD10892,-1333;PD10888,-966;PD10878,-783;PD10871,-750;PD10866,-743;PD10861,-739;PD10698,-718;PD10548,-697;PD10536,-655;PD10529,-618;PD11058,-624;PD11498,-632;PD11626,-639;PD11712,-647;PD11818,-666;PD11913,-689;PD11997,-718;PD12069,-751;PD12132,-791;PD12184,-836;PD12227,-887;PD12262,-945;PD12282,-989;PD12293,-1024;PD12297,-1063;PD12298,-1118;PD12294,-1185;PD12283,-1250;PD12266,-1314;PD12242,-1375;PD12212,-1433;PD12176,-1490;PD12134,-1543;PD12086,-1594;PD12033,-1642;PD11974,-1687;PD11910,-1728;PD11840,-1767;PD11765,-1802;PD11685,-1833;PD11601,-1861;PD11511,-1885;PD11445,-1899;PD11416,-1903;PD11421,-1858;PD11427,-1834;PD11439,-1818;PD11462,-1805;PD11503,-1790;PD11590,-1754;PD11667,-1709;PD11734,-1656;PD11790,-1595;PD11837,-1527;PD11873,-1450;PD11899,-1366;PD11914,-1275;PD11916,-1198;PD11907,-1124;PD11887,-1053;PD11858,-987;PD11820,-927;PD11774,-874;PD11720,-830;PD11658,-795;PD11597,-774;PD11518,-754;PD11431,-739;PD11344,-730;PD11269,-725;PD11262,-918;PD11257,-1214;PD11255,-1646;PD11257,-2096;PD11262,-2446;PD11269,-2718;PD11471,-2738;PD11618,-2756;PD11658,-2764;PD11672,-2770;PD11679,-2805;PD11679,-2812;PD11672,-2818;PD11651,-2822;PD11610,-2824;PD11439,-2827;PD11108,-2827;PD10643,-2824;PD10558,-2820;PD10541,-2817;PD10538,-2812;PD10538,-2812;PU12536,-2812;PD12541,-2778;PD12543,-2772;PD12547,-2767;PD12571,-2758;PD12708,-2738;PD12827,-2723;PD12880,-2713;PD12884,-2422;PD12886,-1731;PD12883,-949;PD12878,-793;PD12875,-758;PD12871,-746;PD12817,-734;PD12708,-718;PD12600,-702;PD12551,-690;PD12538,-654;PD12531,-626;PD13078,-626;PD13624,-626;PD13618,-654;PD13611,-677;PD13603,-691;PD13552,-704;PD13441,-721;PD13329,-737;PD13278,-749;PD13275,-836;PD13272,-1059;PD13270,-1731;PD13271,-2404;PD13273,-2626;PD13276,-2713;PD13328,-2724;PD13445,-2740;PD13607,-2760;PD13614,-2794;PD13621,-2827;PD13076,-2827;PD12635,-2824;PD12555,-2820;PD12539,-2817;PD12536,-2812;PD12536,-2812;PU13913,-2812;PD13919,-2777;PD13923,-2766;PD13942,-2758;PD14052,-2744;PD14173,-2731;PD14209,-2724;PD14232,-2714;PD14246,-2699;PD14253,-2676;PD14259,-2601;PD14265,-2296;PD14267,-1760;PD14266,-1215;PD14261,-889;PD14254,-735;PD14168,-723;PD14001,-704;PD13956,-699;PD13931,-693;PD13921,-685;PD13919,-670;PD13913,-630;PD13918,-626;PD13941,-622;PD14055,-618;PD14680,-618;PD15452,-622;PD15472,-510;PD15491,-397;PD15531,-391;PD15574,-386;PD15566,-451;PD15545,-668;PD15526,-972;PD15519,-1137;PD15483,-1126;PD15445,-1111;PD15432,-992;PD15427,-931;PD15421,-893;PD15412,-870;PD15398,-856;PD15364,-835;PD15312,-816;PD15245,-797;PD15163,-780;PD15070,-764;PD14965,-751;PD14729,-730;PD14695,-729;PD14675,-730;PD14664,-737;PD14659,-749;PD14652,-888;PD14645,-1189;PD14638,-1606;PD14834,-1598;PD15005,-1589;PD15143,-1579;PD15238,-1567;PD15267,-1562;PD15281,-1556;PD15296,-1523;PD15313,-1460;PD15332,-1394;PD15342,-1380;PD15353,-1377;PD15393,-1369;PD15403,-1367;PD15407,-1371;PD15405,-1412;PD15392,-1524;PD15379,-1691;PD15368,-1861;PD15364,-1979;PD15364,-2079;PD15328,-2072;PD15288,-2061;PD15277,-1935;PD15270,-1842;PD15261,-1793;PD15245,-1780;PD15213,-1767;PD15165,-1756;PD15104,-1744;PD14943,-1725;PD14740,-1711;PD14641,-1707;PD14642,-2019;PD14645,-2291;PD14651,-2506;PD14659,-2650;PD14664,-2690;PD14670,-2708;PD14687,-2714;PD14726,-2722;PD14844,-2740;PD15007,-2760;PD15014,-2794;PD15021,-2827;PD14464,-2827;PD14015,-2824;PD13932,-2820;PD13916,-2817;PD13913,-2812;PD13913,-2812;PU; \ No newline at end of file diff --git a/text_to_hpgl.py b/text_to_hpgl.py index 98cf862..7f20609 100644 --- a/text_to_hpgl.py +++ b/text_to_hpgl.py @@ -33,36 +33,13 @@ def _flatten_cubic(p0, p1, p2, p3, n=10): yield (x, y) -def text_to_hpgl(text, font_path, size_pt=72, units_per_pt=14): - """ - Convert text to HPGL string using the given font file. - size_pt: font size in points. - units_per_pt: HPGL units per point (default ~0.35 mm per pt). - Returns HPGL string (IN;SP1;PU x,y;PD;PA x,y;...). - """ - try: - from matplotlib.textpath import TextPath - from matplotlib.font_manager import FontProperties - except ImportError: - raise RuntimeError('matplotlib is required for text-to-HPGL. Install with: pip install matplotlib') - - if not text or not font_path or not os.path.isfile(font_path): - raise ValueError('Need non-empty text and a valid font file path.') - - prop = FontProperties(fname=font_path) - path = TextPath((0, 0), text, size=size_pt, prop=prop) - vertices = path.vertices - codes = path.codes - +def _path_to_segments(vertices, codes, scale): + """Convert a single path (vertices, codes) to list of (PU/PD, x, y) in HPGL units.""" if codes is None: codes = [MOVETO] + [LINETO] * (len(vertices) - 1) - - # Scale to HPGL units (y flip: matplotlib y up, HPGL typically y up too; we keep same) - scale = units_per_pt segments = [] i = 0 contour_start = None - while i < len(codes): code = codes[i] if code == MOVETO: @@ -94,9 +71,44 @@ def text_to_hpgl(text, font_path, size_pt=72, units_per_pt=14): i += 3 else: i += 1 + return segments + + +def text_to_hpgl(text, font_path, size_pt=72, units_per_pt=14): + """ + Convert text to HPGL string using the given font file. + Newlines in text start a new line (stacked vertically). + size_pt: font size in points. + units_per_pt: HPGL units per point (default ~0.35 mm per pt). + Returns HPGL string (IN;SP1;PU x,y;PD;PA x,y;...). + """ + try: + from matplotlib.textpath import TextPath + from matplotlib.font_manager import FontProperties + except ImportError: + raise RuntimeError('matplotlib is required for text-to-HPGL. Install with: pip install matplotlib') + + if not text or not font_path or not os.path.isfile(font_path): + raise ValueError('Need non-empty text and a valid font file path.') + + # Normalize line endings and split into lines + lines = text.replace('\r\n', '\n').replace('\r', '\n').split('\n') + scale = units_per_pt + line_height_pt = size_pt * 1.2 # line spacing + prop = FontProperties(fname=font_path) + all_segments = [] + + for line_index, line in enumerate(lines): + if not line.strip(): + continue + # Each line at its own Y: first line at 0, next at -line_height_pt, etc. (y down) + path = TextPath((0, -line_index * line_height_pt), line, size=size_pt, prop=prop) + vertices = path.vertices + codes = path.codes + all_segments.extend(_path_to_segments(vertices, codes, scale)) out = ['IN', 'SP1'] - for seg in segments: + for seg in all_segments: if seg[0] == 'PU': out.append('PU{},{}'.format(seg[1], seg[2])) else: diff --git a/webui/app.py b/webui/app.py index bd186be..2c2e95f 100644 --- a/webui/app.py +++ b/webui/app.py @@ -29,6 +29,7 @@ app.secret_key = webui_secret_key() app.config['MAX_CONTENT_LENGTH'] = webui_max_upload_mb() * 1024 * 1024 UPLOAD_DIR = os.path.join(ROOT, 'webui', 'uploads') os.makedirs(UPLOAD_DIR, exist_ok=True) +OUTPUT_HPGL_DIR = os.path.join(ROOT, 'output', 'hpgl') FONT_DIRS = [ os.path.join(ROOT, 'font'), os.path.join(ROOT, '.git', 'font'), @@ -119,6 +120,45 @@ def api_text_to_hpgl(): return jsonify({'ok': True, 'filename': session['upload_filename'], 'preview_url': '/api/svg'}) +@app.route('/api/hpgl_files') +def list_hpgl_files(): + """List HPGL filenames in output/hpgl/.""" + if not os.path.isdir(OUTPUT_HPGL_DIR): + return jsonify({'files': []}) + files = [] + for name in sorted(os.listdir(OUTPUT_HPGL_DIR)): + if name.startswith('.'): + continue + path = os.path.join(OUTPUT_HPGL_DIR, name) + if not os.path.isfile(path): + continue + low = name.lower() + if low.endswith('.hpgl') or low.endswith('.plt') or '.' not in name: + files.append(name) + return jsonify({'files': files}) + + +@app.route('/api/load_hpgl', methods=['POST']) +def load_hpgl_from_folder(): + """Set current program from a file in output/hpgl/.""" + data = request.get_json() or {} + filename = (data.get('filename') or '').strip() + if not filename: + return jsonify({'error': 'No filename'}), 400 + if os.path.basename(filename) != filename or '..' in filename: + return jsonify({'error': 'Invalid filename'}), 400 + path = os.path.join(OUTPUT_HPGL_DIR, filename) + if not os.path.isfile(path): + return jsonify({'error': 'File not found'}), 404 + try: + Program.parsefile(path) + except Exception as e: + return jsonify({'error': 'Invalid HPGL: {}'.format(str(e))}), 400 + session['upload_path'] = path + session['upload_filename'] = filename + return jsonify({'ok': True, 'filename': filename, 'preview_url': '/api/svg'}) + + @app.route('/api/upload', methods=['POST']) def upload(): if 'file' not in request.files: @@ -144,6 +184,25 @@ def upload(): }) +@app.route('/api/download_hpgl') +def download_hpgl(): + """Return current program as downloadable HPGL file.""" + p = _get_program() + if p is None: + return jsonify({'error': 'No file loaded'}), 404 + filename = (session.get('upload_filename') or 'export').strip() + if not filename.lower().endswith('.hpgl') and not filename.lower().endswith('.plt'): + filename = filename + '.hpgl' + return ( + str(p), + 200, + { + 'Content-Type': 'application/octet-stream', + 'Content-Disposition': 'attachment; filename="{}"'.format(filename), + }, + ) + + @app.route('/api/dimensions') def dimensions(): """Return current program size in plotter units (e.g. 0.025 mm per unit).""" diff --git a/webui/static/app.js b/webui/static/app.js index 7cf0391..d83a538 100644 --- a/webui/static/app.js +++ b/webui/static/app.js @@ -23,7 +23,8 @@ scaleToBounds: document.getElementById('btnScaleToBounds'), print: document.getElementById('btnPrint'), checkPlotter: document.getElementById('btnCheckPlotter'), - generateHpgl: document.getElementById('btnGenerateHpgl') + generateHpgl: document.getElementById('btnGenerateHpgl'), + exportHpgl: document.getElementById('btnExportHpgl') }; const tabFile = document.getElementById('tabFile'); const tabText = document.getElementById('tabText'); @@ -33,6 +34,7 @@ const fontSelect = document.getElementById('fontSelect'); const textSize = document.getElementById('textSize'); const textMessage = document.getElementById('textMessage'); + const hpglFolderSelect = document.getElementById('hpglFolderSelect'); function setMessage(el, text, type) { el.textContent = text || ''; @@ -93,7 +95,7 @@ }); } - var transformPrintButtons = ['flip', 'rotate90', 'rotate180', 'scaleUp', 'scaleDown', 'centralize', 'scaleToBounds', 'print']; + var transformPrintButtons = ['flip', 'rotate90', 'rotate180', 'scaleUp', 'scaleDown', 'centralize', 'scaleToBounds', 'print', 'exportHpgl']; function setLoaded(loaded) { if (loaded) { @@ -264,9 +266,52 @@ tabText.classList.toggle('active', !isFile); if (panelFile) panelFile.classList.toggle('hidden', !isFile); if (panelText) panelText.classList.toggle('hidden', isFile); + if (isFile && hpglFolderSelect && hpglFolderSelect.options.length <= 1) loadHpglFiles(); if (!isFile && fontSelect && fontSelect.options.length <= 1) loadFonts(); } + function loadHpglFiles() { + if (!hpglFolderSelect) return; + fetch('/api/hpgl_files') + .then(function (r) { return r.json(); }) + .then(function (d) { + var opts = hpglFolderSelect.querySelectorAll('option'); + for (var i = opts.length - 1; i >= 1; i--) opts[i].remove(); + (d.files || []).forEach(function (f) { + var o = document.createElement('option'); + o.value = f; + o.textContent = f; + hpglFolderSelect.appendChild(o); + }); + }) + .catch(function () {}); + } + + if (hpglFolderSelect) { + hpglFolderSelect.addEventListener('change', function () { + var filename = (this.value || '').trim(); + if (!filename) return; + setMessage(printMessage, ''); + fetch('/api/load_hpgl', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ filename: filename }) + }) + .then(function (r) { + return r.json().then(function (d) { + if (!r.ok) throw new Error(d.error || 'Load failed'); + return d; + }); + }) + .then(function () { + refreshStatus(); + }) + .catch(function (e) { + setMessage(printMessage, e.message || 'Load failed', 'error'); + }); + }); + } + function loadFonts() { if (!fontSelect) return; fetch('/api/fonts') @@ -287,6 +332,12 @@ if (tabFile) tabFile.addEventListener('click', function () { showTab('file'); }); if (tabText) tabText.addEventListener('click', function () { showTab('text'); }); + if (buttons.exportHpgl) { + buttons.exportHpgl.addEventListener('click', function () { + window.location.href = '/api/download_hpgl'; + }); + } + if (buttons.generateHpgl && textInput && fontSelect) { buttons.generateHpgl.addEventListener('click', function () { var text = (textInput.value || '').trim(); @@ -324,6 +375,7 @@ } refreshStatus(); + loadHpglFiles(); updatePlotterInfo(); setInterval(updatePlotterInfo, 10000); })(); diff --git a/webui/static/style.css b/webui/static/style.css index e44c331..7070cb7 100644 --- a/webui/static/style.css +++ b/webui/static/style.css @@ -155,6 +155,23 @@ body { background: var(--accent-hover); } +.btn-export-hpgl { + width: 100%; + margin-top: 0.5rem; + padding: 0.5rem 0.75rem; + font-size: 0.875rem; + background: var(--surface); + border: 1px solid var(--border); + border-radius: 6px; + color: var(--text); + cursor: pointer; +} + +.btn-export-hpgl:hover:not(:disabled) { + background: var(--border); + border-color: var(--accent); +} + .status { display: flex; gap: 1rem; diff --git a/webui/templates/index.html b/webui/templates/index.html index 7b2fdbf..b3951c7 100644 --- a/webui/templates/index.html +++ b/webui/templates/index.html @@ -24,6 +24,10 @@