11#if __has_include("stb_truetype.h")
22# define PROCESSING_HAS_STB_TRUETYPE 1
33# define STB_TRUETYPE_IMPLEMENTATION
4+ # if defined(_MSC_VER)
5+ # pragma warning(push)
6+ # pragma warning(disable: 4365)
7+ # endif
48# include " stb_truetype.h"
9+ # if defined(_MSC_VER)
10+ # pragma warning(pop)
11+ # endif
512#else
613# define PROCESSING_HAS_STB_TRUETYPE 0
714#endif
815
916#include " Processing.h"
17+ #ifdef _MSC_VER
18+ #pragma warning(push)
19+ #pragma warning(disable: 4365 4245 4100 4189)
20+ #endif
1021#ifdef __EMSCRIPTEN__
1122#include < emscripten.h>
1223#include < emscripten/html5.h>
1627#undef GL_QUAD_STRIP
1728#define GL_QUAD_STRIP GL_TRIANGLE_STRIP
1829#endif
30+
1931#include < csignal>
2032#include < cstdlib>
2133#include < cmath>
3042#include < objc/message.h>
3143#include < dlfcn.h>
3244#endif
45+
3346#ifndef _WIN32
3447#include < thread>
3548#endif
49+
3650#include < vector>
3751#include < array>
3852#include < string>
5266// Uncomment + drop stb_image_write.h to enable saveFrame()/save():
5367// #define STB_IMAGE_WRITE_IMPLEMENTATION
5468#define STB_IMAGE_WRITE_IMPLEMENTATION
69+ #if defined(__clang__)
5570#pragma clang diagnostic push
5671#pragma clang diagnostic ignored "-Wdeprecated-declarations"
72+ #elif defined(__GNUC__)
5773#pragma GCC diagnostic push
5874#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
75+ #endif
76+ #ifdef _MSC_VER
77+ #pragma warning(push)
78+ #pragma warning(disable: 4365)
79+ #endif
5980#include " stb_image_write.h"
81+ #ifdef _MSC_VER
82+ #pragma warning(pop)
83+ #endif
84+ #if defined(__clang__)
6085#pragma clang diagnostic pop
86+ #elif defined(__GNUC__)
6187#pragma GCC diagnostic pop
88+ #endif
6289
6390// ── Manual glu replacements (no GLU header needed) ───────────────────────────
6491static void _gluPerspective (double fovY_deg, double aspect, double zNear, double zFar) {
@@ -161,6 +188,31 @@ std::function<void()> _onWindowMoved;
161188
162189namespace Processing {
163190
191+ static FILE * processingOpenFile (const char * path, const char * mode) {
192+ #ifdef _WIN32
193+ FILE * file = nullptr ;
194+ return ::fopen_s (&file, path, mode) == 0 ? file : nullptr ;
195+ #else
196+ return ::fopen (path, mode);
197+ #endif
198+ }
199+
200+ static FILE * processingOpenPipe (const char * command, const char * mode) {
201+ #ifdef _WIN32
202+ return ::_popen (command, mode);
203+ #else
204+ return ::popen (command, mode);
205+ #endif
206+ }
207+
208+ static int processingClosePipe (FILE * pipe) {
209+ #ifdef _WIN32
210+ return ::_pclose (pipe);
211+ #else
212+ return ::pclose (pipe);
213+ #endif
214+ }
215+
164216static void _doEnableDebugConsole () {
165217#ifdef _WIN32
166218 if (AllocConsole ()) {
@@ -312,8 +364,8 @@ color PApplet::makeColor(float gray,float alpha){
312364 float br=gray/colorMaxB;
313365 br=::std::fmax (0 .f ,::std::fmin (1 .f ,br));
314366 int v=(int )(br*255 );
315- unsigned int a=::std::fmax (0 .f ,::std::fmin (1 .f ,alpha/colorMaxA))*255 ;
316- return colorVal (v,v,v,( int )a );
367+ unsigned int a=static_cast < unsigned int >( ::std::fmax (0 .f ,::std::fmin (1 .f ,alpha/colorMaxA))*255 . 0f ) ;
368+ return colorVal (v,v,v,static_cast < int >(a) );
317369 }
318370 return makeColor (gray,gray,gray,alpha);
319371}
@@ -2271,7 +2323,7 @@ void PApplet::drawBitmapStr(float x, float y, const ::std::string& s, int scale)
22712323}
22722324
22732325float PApplet::bitmapStrWidth (const ::std::string& s, int scale) {
2274- return s.size () * (BF_GW +1 ) * scale;
2326+ return static_cast < float >( s.size ()) * static_cast < float > (BF_GW +1 ) * static_cast < float >( scale) ;
22752327}
22762328
22772329// -- TTF rendering -------------------------------------------------------------
@@ -2376,7 +2428,7 @@ void PApplet::renderText(const ::std::string& msg, float x, float y) {
23762428 // Bitmap fallback
23772429 int sc = ::std::max (1 ,(int )(g_textSize/8 .0f ));
23782430 // Shift so baseline sits at y (bitmap font: ascent = BF_GH-2 rows)
2379- float ascent = (BF_GH - 2 ) * sc ;
2431+ float ascent = static_cast < float > (BF_GH - 2 ) * static_cast < float >(sc) ;
23802432 drawBitmapStr (dx, dy - ascent, ls[li], sc);
23812433 }
23822434}
@@ -2515,7 +2567,7 @@ float PApplet::textAscent() {
25152567 }
25162568#endif
25172569 int sc = ::std::max (1 ,(int )(g_textSize/8 .0f ));
2518- return (BF_GH - 2 ) * sc ;
2570+ return static_cast < float > (BF_GH - 2 ) * static_cast < float >(sc) ;
25192571}
25202572
25212573float PApplet::textDescent () {
@@ -2550,7 +2602,9 @@ PImage* PApplet::loadImage(const ::std::string& path){
25502602 // Handle URLs: download with curl/wget and validate image magic bytes
25512603 if (path.size ()>7 && (path.substr (0 ,7 )==" http://" || path.substr (0 ,8 )==" https://" )){
25522604#ifdef _WIN32
2553- ::std::string tmp=::std::string (getenv (" TEMP" )?getenv (" TEMP" ):" C:\\ Temp" )+" \\ pg_img_" ;
2605+ ::std::string tempDir = processingEnvironmentVariable (" TEMP" );
2606+ if (tempDir.empty ()) tempDir = " C:\\ Temp" ;
2607+ ::std::string tmp=tempDir+" \\ pg_img_" ;
25542608#else
25552609 ::std::string tmp=" /tmp/pg_img_" ;
25562610#endif
@@ -2561,7 +2615,7 @@ PImage* PApplet::loadImage(const ::std::string& path){
25612615 for (char & c:bn) if (c==' :' ||c==' *' ||c==' <' ||c==' >' ||c==' |' ) c=' _' ;
25622616 tmp+=bn;
25632617 auto isValidImg=[&]()->bool {
2564- FILE * f2=fopen (tmp.c_str ()," rb" ); if (!f2) return false ;
2618+ FILE * f2=processingOpenFile (tmp.c_str ()," rb" ); if (!f2) return false ;
25652619 fseek (f2,0 ,SEEK_END ); long sz=ftell (f2); fseek (f2,0 ,SEEK_SET );
25662620 unsigned char h[4 ]={}; fread (h,1 ,4 ,f2); fclose (f2);
25672621 if (sz<100 ) return false ;
@@ -2594,9 +2648,8 @@ PImage* PApplet::loadImage(const ::std::string& path){
25942648 }
25952649 // Search paths: current dir, data/, files/, and sketch subdirs
25962650 // Check PROCESSING_SKETCH_PATH env var set by IDE
2597- ::std::string _sketchDir;
2598- if (const char * _sp = ::std::getenv (" PROCESSING_SKETCH_PATH" ))
2599- _sketchDir = ::std::string (_sp) + " /" ;
2651+ ::std::string _sketchDir = processingEnvironmentVariable (" PROCESSING_SKETCH_PATH" );
2652+ if (!_sketchDir.empty ()) _sketchDir += " /" ;
26002653 // Also get the directory of the running executable
26012654 ::std::string _exeDir;
26022655 {
@@ -2834,13 +2887,13 @@ void PApplet::filter(int mode, float param) {
28342887 int r=buf[i*4 ],g=buf[i*4 +1 ],b=buf[i*4 +2 ];
28352888 int grey=(r+g+b)/3 ;
28362889 if (mode==GRAY ) { buf[i*4 ]=buf[i*4 +1 ]=buf[i*4 +2 ]=(unsigned char )grey; }
2837- else if (mode==INVERT ) { buf[i*4 ]=255 -r; buf[i*4 +1 ]=255 -g; buf[i*4 +2 ]=255 -b; }
2890+ else if (mode==INVERT ) { buf[i*4 ]=static_cast < unsigned char >( 255 -r) ; buf[i*4 +1 ]=static_cast < unsigned char >( 255 -g) ; buf[i*4 +2 ]=static_cast < unsigned char >( 255 -b) ; }
28382891 else if (mode==THRESHOLD ) { unsigned char t=(grey>param*255 )?255 :0 ; buf[i*4 ]=buf[i*4 +1 ]=buf[i*4 +2 ]=t; }
2839- else if (mode==OPAQUE ) { buf[i*4 +3 ]=255 ; }
2892+ else if (mode==OPAQUE ) { buf[i*4 +3 ]=static_cast < unsigned char >( 255 ) ; }
28402893 else if (mode==POSTERIZE ) {
28412894 int levels = ::std::max (2 ,(int )param);
28422895 auto post = [levels](int v){ return (int )((int )(v*(levels-1 )/255 .0f +0 .5f )*255 /(levels-1 )); };
2843- buf[i* 4 ]= post (r); buf[i* 4 + 1 ]= post (g); buf[i* 4 + 2 ]= post (b);
2896+ buf[static_cast < size_t >(i)* 4u ]= static_cast < unsigned char >( post (r)) ; buf[static_cast < size_t >(i)* 4u + 1u ]= static_cast < unsigned char >( post (g)) ; buf[static_cast < size_t >(i)* 4u + 2u ]= static_cast < unsigned char >( post (b) );
28442897 }
28452898 }
28462899 } else if (mode == BLUR ) {
@@ -2855,7 +2908,7 @@ void PApplet::filter(int mode, float param) {
28552908 sr+=tmp[j]; sg+=tmp[j+1 ]; sb+=tmp[j+2 ]; sa+=tmp[j+3 ]; cnt++;
28562909 }
28572910 int i=(y*w+x2)*4 ;
2858- buf[i]=sr/cnt; buf[i+1 ]=sg/cnt; buf[i+2 ]=sb/cnt; buf[i+3 ]=sa/cnt;
2911+ buf[i]=static_cast < unsigned char >( sr/cnt) ; buf[i+1 ]=static_cast < unsigned char >( sg/cnt) ; buf[i+2 ]=static_cast < unsigned char >( sb/cnt) ; buf[i+3 ]=static_cast < unsigned char >( sa/cnt) ;
28592912 }
28602913 } else if (mode == ERODE || mode == DILATE ) {
28612914 ::std::vector<unsigned char > tmp (buf);
@@ -3050,7 +3103,7 @@ void PApplet::saveFrame(const ::std::string& filename) {
30503103 for (int x = 0 ; x < w * 3 ; x++)
30513104 ::std::swap (px[y*w*3 +x], px[(h-1 -y)*w*3+x]);
30523105 ::std::string ext = fn.size () > 4 ? fn.substr (fn.size ()-4 ) : " " ;
3053- for (auto & c : ext) c = tolower (c );
3106+ for (auto & c : ext) c = static_cast < char >( tolower (static_cast < unsigned char >(c)) );
30543107 int ok = 0 ;
30553108 if (ext == " .png" ) ok = stbi_write_png (fn.c_str (), w, h, 3 , px.data (), w*3 );
30563109 else if (ext == " .jpg" || ext == " jpeg" ) ok = stbi_write_jpg (fn.c_str (), w, h, 3 , px.data (), 95 );
@@ -3622,22 +3675,22 @@ void PApplet::run(){
36223675 {
36233676 ::std::string _homeDir;
36243677#ifdef _WIN32
3625- if ( const char * h = :: std::getenv (" USERPROFILE" )) _homeDir = h ;
3678+ _homeDir = processingEnvironmentVariable (" USERPROFILE" );
36263679#else
3627- if ( const char * h = :: std::getenv (" HOME" )) _homeDir = h ;
3680+ _homeDir = processingEnvironmentVariable (" HOME" );
36283681#endif
36293682 ::std::string _modePath;
3630- if ( const char * mp = :: std::getenv (" PROCESSING_MODE_PATH" ))
3631- _modePath = :: std::string (mp) + " /" ;
3683+ _modePath = processingEnvironmentVariable (" PROCESSING_MODE_PATH" );
3684+ if (! _modePath. empty ()) _modePath += " /" ;
36323685
36333686 // Font name used by Processing4
36343687 const ::std::string _font = " ProcessingSansPro-Regular.ttf" ;
36353688
36363689 // Check Documents/Processing on Windows (user sketchbook)
36373690 ::std::string _docsPath;
36383691#ifdef _WIN32
3639- if ( const char * ud = ::std::getenv (" USERPROFILE" ))
3640- _docsPath = :: std::string (ud) + " /Documents/Processing/" ;
3692+ ::std::string userProfile = processingEnvironmentVariable (" USERPROFILE" );
3693+ if (!userProfile. empty ()) _docsPath = userProfile + " /Documents/Processing/" ;
36413694#endif
36423695
36433696 if (!tryLoadTTF (" fonts/" + _font, g_textSize) &&
@@ -4479,7 +4532,7 @@ static PShape* svgLoad(const ::std::string& path){
44794532 // Search paths
44804533 ::std::vector<::std::string> tries={path," data/" +path," files/" +path};
44814534 ::std::string found;
4482- for (auto & t:tries){FILE * f=fopen (t.c_str ()," r" );if (f){fclose (f);found=t;break ;}}
4535+ for (auto & t:tries){FILE * f=processingOpenFile (t.c_str ()," r" );if (f){fclose (f);found=t;break ;}}
44834536 if (found.empty ()){::std::cerr<<" loadShape: file not found: " <<path<<" \n " ;return new PShape ();}
44844537
44854538 ::std::ifstream f (found);
@@ -4681,7 +4734,7 @@ static ::std::unordered_map<::std::string,GLuint> objLoadMtl(const ::std::string
46814734static PShape* objLoad (const ::std::string& path){
46824735 ::std::vector<::std::string> tries={path," data/" +path," files/" +path};
46834736 ::std::string found;
4684- for (auto & t:tries){FILE * f2=fopen (t.c_str ()," r" );if (f2){fclose (f2);found=t;break ;}}
4737+ for (auto & t:tries){FILE * f2=processingOpenFile (t.c_str ()," r" );if (f2){fclose (f2);found=t;break ;}}
46854738 if (found.empty ()){::std::cerr<<" loadShape: OBJ not found: " <<path<<" \n " ;return new PShape ();}
46864739
46874740 // Get directory for relative texture paths
@@ -5007,7 +5060,7 @@ PFont* PApplet::createFont(const ::std::string& name, float size, bool /*smooth*
50075060 // Also search system font dirs recursively (Linux: fc-list output)
50085061 #ifndef _WIN32
50095062 {
5010- FILE * fc = popen ((" fc-list : file | grep -i '" + nameNoExt + " ' | head -5" ).c_str (), " r" );
5063+ FILE * fc = processingOpenPipe ((" fc-list : file | grep -i '" + nameNoExt + " ' | head -5" ).c_str (), " r" );
50115064 if (fc) {
50125065 char buf[512 ];
50135066 while (fgets (buf, sizeof (buf), fc)) {
@@ -5022,7 +5075,7 @@ PFont* PApplet::createFont(const ::std::string& name, float size, bool /*smooth*
50225075 if (!fpath.empty ()) paths.push_back (fpath);
50235076 }
50245077 }
5025- pclose (fc);
5078+ processingClosePipe (fc);
50265079 }
50275080 }
50285081 #endif
@@ -5078,26 +5131,26 @@ ::std::string PApplet::selectInput(const ::std::string& prompt,const ::std::stri
50785131 (void )prompt; return " " ;
50795132#endif
50805133 ::std::string cmd=" zenity --file-selection --title=\" " +prompt+" \" 2>/dev/null" ;
5081- FILE * p=popen (cmd.c_str ()," r" ); if (!p)return " " ;
5082- char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); pclose (p);
5134+ FILE * p=processingOpenPipe (cmd.c_str ()," r" ); if (!p)return " " ;
5135+ char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); processingClosePipe (p);
50835136 ::std::string r (buf); if (!r.empty ()&&r.back ()==' \n ' )r.pop_back (); return r;
50845137}
50855138::std::string PApplet::selectOutput (const ::std::string& prompt,const ::std::string&){
50865139#ifdef __EMSCRIPTEN__
50875140 (void )prompt; return " " ;
50885141#endif
50895142 ::std::string cmd=" zenity --file-selection --save --title=\" " +prompt+" \" 2>/dev/null" ;
5090- FILE * p=popen (cmd.c_str ()," r" ); if (!p)return " " ;
5091- char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); pclose (p);
5143+ FILE * p=processingOpenPipe (cmd.c_str ()," r" ); if (!p)return " " ;
5144+ char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); processingClosePipe (p);
50925145 ::std::string r (buf); if (!r.empty ()&&r.back ()==' \n ' )r.pop_back (); return r;
50935146}
50945147::std::string PApplet::selectFolder (const ::std::string& prompt){
50955148#ifdef __EMSCRIPTEN__
50965149 (void )prompt; return " " ;
50975150#endif
50985151 ::std::string cmd=" zenity --file-selection --directory --title=\" " +prompt+" \" 2>/dev/null" ;
5099- FILE * p=popen (cmd.c_str ()," r" ); if (!p)return " " ;
5100- char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); pclose (p);
5152+ FILE * p=processingOpenPipe (cmd.c_str ()," r" ); if (!p)return " " ;
5153+ char buf[4096 ]=" " ; fgets (buf,sizeof (buf),p); processingClosePipe (p);
51015154 ::std::string r (buf); if (!r.empty ()&&r.back ()==' \n ' )r.pop_back (); return r;
51025155}
51035156
@@ -5111,9 +5164,8 @@ PImage* PApplet::requestImage(const ::std::string& path){
51115164 ::std::thread ([img, path]{
51125165 // Resolve search paths same as loadImage
51135166 // Check PROCESSING_SKETCH_PATH env var set by IDE
5114- ::std::string _sketchDir;
5115- if (const char * _sp = ::std::getenv (" PROCESSING_SKETCH_PATH" ))
5116- _sketchDir = ::std::string (_sp) + " /" ;
5167+ ::std::string _sketchDir = processingEnvironmentVariable (" PROCESSING_SKETCH_PATH" );
5168+ if (!_sketchDir.empty ()) _sketchDir += " /" ;
51175169 // Also get the directory of the running executable
51185170 ::std::string _exeDir;
51195171 {
@@ -5139,7 +5191,7 @@ PImage* PApplet::requestImage(const ::std::string& path){
51395191 };
51405192 ::std::string found;
51415193 for (auto & t : tries) {
5142- FILE * f = fopen (t.c_str (), " rb" );
5194+ FILE * f = processingOpenFile (t.c_str (), " rb" );
51435195 if (f) { fclose (f); found = t; break ; }
51445196 }
51455197 if (found.empty ()) {
@@ -5248,8 +5300,8 @@ PImage getRegion(int x,int y,int w,int h){
52485300
52495301::std::vector<::std::string> PApplet::loadStrings (const ::std::string& path) {
52505302 ::std::vector<::std::string> lines;
5251- ::std::string sketchDir;
5252- if (const char * sp = :: std::getenv ( " PROCESSING_SKETCH_PATH " )) sketchDir = :: std::string (sp) + " /" ;
5303+ ::std::string sketchDir = processingEnvironmentVariable ( " PROCESSING_SKETCH_PATH " ) ;
5304+ if (!sketchDir. empty ( )) sketchDir += " /" ;
52535305 ::std::ifstream f (path);
52545306 if (!f) f.open (sketchDir + path);
52555307 if (!f) f.open (sketchDir + " data/" + path);
@@ -5321,3 +5373,7 @@ ::std::string PApplet::binary(int v) {
53215373
53225374} // namespace Processing
53235375
5376+ #ifdef _MSC_VER
5377+ #pragma warning(pop)
5378+ #endif
5379+
0 commit comments