Browse code

UI: add ability to put balloons on screen

Dario Rodriguez authored on 21/10/2020 22:06:25
Showing 3 changed files
... ...
@@ -24,6 +24,23 @@
24 24
 
25 25
 #define RECTFILL(r,rx,ry,rw,rh) (r).x=(rx),(r).y=(ry),(r).w=(rw),(r).h=(rh)
26 26
 
27
+#if SDL_BYTEORDER==SDL_BIG_ENDIAN
28
+#define CHARRGBA2UINT(rgba) ((((Uint32)(((unsigned char *)rgba)[0]))<<24) \
29
+                            |(((Uint32)(((unsigned char *)rgba)[1]))<<16) \
30
+                            |(((Uint32)(((unsigned char *)rgba)[2]))<<8)  \
31
+                            |((Uint32)(((unsigned char *)rgba)[3])))
32
+#else
33
+#define CHARRGBA2UINT(rgba) ((((Uint32)(((unsigned char *)rgba)[3]))<<24) \
34
+                            |(((Uint32)(((unsigned char *)rgba)[2]))<<16) \
35
+                            |(((Uint32)(((unsigned char *)rgba)[1]))<<8)  \
36
+                            |((Uint32)(((unsigned char *)rgba)[0])))
37
+#endif
38
+
39
+
40
+static int reui_fillrounded(SDL_Surface *dst, int xo, int yo, int w, int h, int r, char *rgba);
41
+static int reui_triangle(SDL_Surface *dst, int x, int y, int w, int h, char direction, char *rgba);
42
+
43
+
27 44
 reui_t *
28 45
 reui_init()
29 46
 {
... ...
@@ -223,4 +240,239 @@ reui_printf(reui_t *ui, int x, int y, char *rgba, char *format, ...)
223 240
         return(0);
224 241
 }
225 242
 
243
+int
244
+reui_balloon(reui_t *ui, char direction, int x, int y, char *rgbafg, char *rgbabg, char *str, int nchar)
245
+{
246
+        char buf[1024];
247
+        SDL_Surface *bgsurface;
248
+        SDL_Surface *fgsurface;
249
+        SDL_Texture *tex;
250
+        SDL_Color c={((unsigned char *)rgbafg)[0],
251
+                     ((unsigned char *)rgbafg)[1],
252
+                     ((unsigned char *)rgbafg)[2],
253
+                     ((unsigned char *)rgbafg)[3]};
254
+        SDL_Rect dstrect;
255
+        Uint32 rmask, gmask, bmask, amask;
256
+        int trianglew,triangleh;
257
+        int marginw,marginh;
258
+        int marginoffx,marginoffy;
259
+        int radius;
260
+        int offx,offy;
261
+        if(ui==NULL || rgbafg==NULL || rgbabg==NULL || (str==NULL && nchar!=0))
262
+                return(-1);
263
+#if SDL_BYTEORDER==SDL_BIG_ENDIAN
264
+        rmask=0xff000000;
265
+        gmask=0x00ff0000;
266
+        bmask=0x0000ff00;
267
+        amask=0x000000ff;
268
+#else
269
+        rmask=0x000000ff;
270
+        gmask=0x0000ff00;
271
+        bmask=0x00ff0000;
272
+        amask=0xff000000;
273
+#endif
274
+        if(nchar<sizeof(buf)) {
275
+                memcpy(buf,str,nchar);
276
+                buf[nchar]='\0';
277
+        } else {
278
+                memcpy(buf,str,sizeof(buf)-1);
279
+                buf[sizeof(buf)-1]='\0';
280
+        }
281
+        if((fgsurface=TTF_RenderUTF8_Blended(ui->font,buf,c))==NULL)
282
+                return(-1);
283
+        trianglew=ui->fontwidth;
284
+        triangleh=ui->fontheight/2;
285
+        marginw=ui->fontwidth*4/3;
286
+        marginh=ui->fontheight/3;
287
+        marginoffx=0;
288
+        marginoffy=-ui->fontheight/18;
289
+        radius=ui->fontheight/2;
290
+        if((bgsurface=SDL_CreateRGBSurface(0
291
+          ,(fgsurface->w+marginw*2)+((direction=='w' || direction=='e')?trianglew:0)
292
+          ,(fgsurface->h+marginh*2)+((direction=='n' || direction=='s')?triangleh:0)
293
+          ,32, rmask, gmask, bmask, amask))==NULL) {
294
+                if(fgsurface!=NULL)
295
+                        SDL_FreeSurface(fgsurface),fgsurface=NULL;
296
+                return(-1);
297
+        }
298
+        if(direction=='n') {
299
+                reui_fillrounded(bgsurface,0,triangleh-1,bgsurface->w,bgsurface->h-triangleh,radius,rgbabg);
300
+                reui_triangle(bgsurface,(bgsurface->w-trianglew)/2,0,trianglew,triangleh,direction,rgbabg);
301
+                RECTFILL(dstrect,marginw+marginoffx,triangleh+marginh+marginoffy,fgsurface->w,fgsurface->h);
302
+                SDL_BlitSurface(fgsurface,NULL,bgsurface,&dstrect);
303
+                offx=-bgsurface->w/2;
304
+                offy=0;
305
+        } else if(direction=='e') {
306
+                reui_fillrounded(bgsurface,0,0,bgsurface->w-trianglew,bgsurface->h,radius,rgbabg);
307
+                reui_triangle(bgsurface,bgsurface->w-trianglew,(bgsurface->h-triangleh)/2,trianglew,triangleh,direction,rgbabg);
308
+                RECTFILL(dstrect,marginw+marginoffx,marginh+marginoffy,fgsurface->w,fgsurface->h);
309
+                SDL_BlitSurface(fgsurface,NULL,bgsurface,&dstrect);
310
+                offx=-bgsurface->w;
311
+                offy=-bgsurface->h/2;
312
+        } else if(direction=='s') {
313
+                reui_fillrounded(bgsurface,0,0,bgsurface->w,bgsurface->h-triangleh,radius,rgbabg);
314
+                reui_triangle(bgsurface,(bgsurface->w-trianglew)/2,bgsurface->h-triangleh,trianglew,triangleh,direction,rgbabg);
315
+                RECTFILL(dstrect,marginw+marginoffx,marginh+marginoffy,fgsurface->w,fgsurface->h);
316
+                SDL_BlitSurface(fgsurface,NULL,bgsurface,&dstrect);
317
+                offx=-bgsurface->w/2;
318
+                offy=-bgsurface->h;
319
+        } else if(direction=='w') {
320
+                reui_fillrounded(bgsurface,trianglew,0,bgsurface->w-trianglew,bgsurface->h,radius,rgbabg);
321
+                reui_triangle(bgsurface,0,(bgsurface->h-triangleh)/2,trianglew,triangleh,direction,rgbabg);
322
+                RECTFILL(dstrect,trianglew+marginw+marginoffx,marginh+marginoffy,fgsurface->w,fgsurface->h);
323
+                SDL_BlitSurface(fgsurface,NULL,bgsurface,&dstrect);
324
+                offx=0;
325
+                offy=-bgsurface->h/2;
326
+        } else { /* default: center */
327
+                reui_fillrounded(bgsurface,0,0,bgsurface->w,bgsurface->h,radius,rgbabg);
328
+                RECTFILL(dstrect,marginw+marginoffx,marginh+marginoffy,fgsurface->w,fgsurface->h);
329
+                SDL_BlitSurface(fgsurface,NULL,bgsurface,&dstrect);
330
+                offx=-bgsurface->w/2;
331
+                offy=-bgsurface->h/2;
332
+        }
333
+        if((tex=SDL_CreateTextureFromSurface(ui->renderer,bgsurface))==NULL) {
334
+                SDL_FreeSurface(fgsurface),fgsurface=NULL;
335
+                SDL_FreeSurface(bgsurface),bgsurface=NULL;
336
+                return(-1);
337
+        }
338
+        RECTFILL(dstrect,x+offx,y+offy,bgsurface->w,bgsurface->h);
339
+        SDL_RenderCopy(ui->renderer,tex,NULL,&dstrect);
340
+        ui->rendererdirty=1;
341
+        SDL_FreeSurface(fgsurface),fgsurface=NULL;
342
+        SDL_FreeSurface(bgsurface),bgsurface=NULL;
343
+        SDL_DestroyTexture(tex),tex=NULL;
344
+        return(0);
345
+
346
+}
347
+
348
+
349
+
350
+/*
351
+ * https://sdl.libsdl.narkive.com/rX3aNgKp/rectangle-with-round-corners-in-sdl
352
+ *
353
+ * static int fill_rounded_box_b(SDL_Surface* dst, int xo, int yo,
354
+ *                               int w, int h, int r, Uint32 color);
355
+ *
356
+ * by "Sami N��t�nen" (s***@bayminer.com)
357
+ * (lightly edited to conform to this file code style and semantics)
358
+ *
359
+ * draws a rounded box with...
360
+ *   corner radius of 'r'
361
+ *   width of 'w'
362
+ *   and height of 'h'
363
+ *
364
+ * draws the box right and down of...
365
+ *   x-offset xo
366
+ *   y-offset yo
367
+ *
368
+ * returns -1 if 2*r is bigger than w or h
369
+ *           and draws nothing
370
+ * returns 0 on success
371
+ */
372
+static int
373
+reui_fillrounded(SDL_Surface *dst, int xo, int yo, int w, int h, int r, char *rgba)
374
+{
375
+        int yd=(dst->pitch)/(dst->format->BytesPerPixel);
376
+        Uint32 *pixels=NULL;
377
+        int x,y,i,j;
378
+        int rpsqrt2= (int) (r/sqrt(2));
379
+        int sy,ey,sx,ex;
380
+        int d,x2m1;
381
+        Uint32 color;
382
+        if(dst==NULL || rgba==NULL || xo<0 || y0<0 || (xo+w)>dst->w || (yo+h)>dst->h)
383
+                return(-1); /* sanity check failed */
384
+        color=CHARRGBA2UINT(rgba);
385
+        w/=2;
386
+        h/=2;
387
+        xo+=w;
388
+        yo+=h;
389
+        w-=r;
390
+        h-=r;
391
+        if(w<0||h<0)
392
+                return(-1);
393
+        SDL_LockSurface(dst);
394
+        pixels=(Uint32*)(dst->pixels);
395
+        sy=(yo-h)*yd;
396
+        ey=(yo+h)*yd;
397
+        sx=(xo-w);
398
+        ex=(xo+w);
399
+        for(i=sy;i<=ey;i+=yd) {
400
+                for(j=sx-r;j<=ex+r;j++) {
401
+                        pixels[i+j]=color;
402
+                }
403
+        }
404
+        d=-r;
405
+        x2m1=-1;
406
+        y=r;
407
+        for(x=0;x<=rpsqrt2;x++) {
408
+                x2m1+=2;
409
+                d+=x2m1;
410
+                if(d>=0) {
411
+                        y--;
412
+                        d-=(y*2);
413
+                }
414
+                for(i=sx-x;i<=ex+x;i++)
415
+                        pixels[sy-y*yd+i]=color;
416
+
417
+                for(i=sx-y;i<=ex+y;i++)
418
+                        pixels[sy-x*yd+i]=color;
419
+
420
+                for(i=sx-y;i<=ex+y;i++)
421
+                        pixels[ey+x*yd+i]=color;
422
+
423
+                for(i=sx-x;i<=ex+x;i++)
424
+                        pixels[ey+y*yd+i]=color;
425
+        }
426
+        SDL_UnlockSurface(dst);
427
+        return(0);
428
+}
429
+
430
+/* end of external code */
431
+
432
+static int
433
+reui_triangle(SDL_Surface *dst, int x, int y, int w, int h, char direction, char *rgba)
434
+{
435
+        Uint32 color;
436
+        SDL_Rect dstrect;
437
+        int i;
438
+        int myw,myh;
439
+        if(dst==NULL || rgba==NULL)
440
+                return(-1);
441
+        color=CHARRGBA2UINT(rgba);
442
+        SDL_LockSurface(dst);
443
+        if(direction=='n') {
444
+                for(i=0;i<h;i++) {
445
+                        myw=(i*w*2)/(3*h);
446
+                        myw=(myw<0)?1:(myw>w)?w:myw;
447
+                        RECTFILL(dstrect,x+(w-myw)/2,y+i,myw,1);
448
+                        SDL_FillRect(dst,&dstrect,color);
449
+                }
450
+        } else if(direction=='e') {
451
+                for(i=0;i<w;i++) {
452
+                        myh=(i*h*2)/(3*w);
453
+                        myh=(myh<0)?1:(myh>h)?h:myh;
454
+                        RECTFILL(dstrect,x+w-1-i,y+(h-myh)/2,1,myh);
455
+                        SDL_FillRect(dst,&dstrect,color);
456
+                }
457
+        } else if(direction=='s') {
458
+                for(i=0;i<h;i++) {
459
+                        myw=(i*w*2)/(3*h);
460
+                        myw=(myw<0)?1:(myw>w)?w:myw;
461
+                        RECTFILL(dstrect,x+(w-myw)/2,y+h-1-i,myw,1);
462
+                        SDL_FillRect(dst,&dstrect,color);
463
+                }
464
+        } else if(direction=='w') {
465
+                for(i=0;i<w;i++) {
466
+                        myh=(i*h*2)/(3*w);
467
+                        myh=(myh<0)?1:(myh>h)?h:myh;
468
+                        RECTFILL(dstrect,x+i,y+(h-myh)/2,1,myh);
469
+                        SDL_FillRect(dst,&dstrect,color);
470
+                }
471
+        } else { /* default: center */
472
+                RECTFILL(dstrect,x,y,w,h);
473
+                SDL_FillRect(dst,&dstrect,color);
474
+        }
475
+        SDL_UnlockSurface(dst);
476
+        return(0);
477
+}
226 478
 
... ...
@@ -48,3 +48,5 @@ int reui_printf(reui_t *ui, int x, int y, char *rgba, char *format, ...) __attri
48 48
 int reui_printf(reui_t *ui, int x, int y, char *rgba, char *format, ...);
49 49
 #endif
50 50
 
51
+int reui_balloon(reui_t *ui, char direction, int x, int y, char *rgbafg, char *rgbabg, char *str, int nchar);
52
+
... ...
@@ -1040,6 +1040,7 @@ re_drawcontents(re_t *re)
1040 1040
                                         reui_write(re->ui,re->x+re->ui->fontwidth*(re->curcol-re->origincol),y,"\xff\xff\xff\xff",curptr,redata_generic_utf8charlen(curptr,curptrlen));
1041 1041
                                 }
1042 1042
 #warning TODO: if it is one of  '[','{','<','>','}',']', highlight the matching bracket/parens/anglebracket.
1043
+#warning When searching for matching backet/..., count only the ones in the same highlighting color.
1043 1044
 #warning If it is ourside of the visible part of the code, put a comic baloon (with some transparency) in that dir. (up, down or right) at the correct height/position to mark the direction of where it is.
1044 1045
 #warning TODO: Select(control+k+b/control+k+k/...)
1045 1046
                         }
... ...
@@ -1053,6 +1054,20 @@ re_drawcontents(re_t *re)
1053 1054
         }
1054 1055
         re->contentsdirty=0;
1055 1056
         re->ui->rendererdirty=1;
1057
+#if 1
1058
+{
1059
+char sampletext[]={"Here is the top"};
1060
+char sampletextlarge[]={"void *memcpy(void *dest, const void *src, size_t n)"};
1061
+reui_balloon(re->ui, 'n', re->x+re->w/2, re->y, "\xff\x00\x00\xff", "\x00\x00\xff\x80",sampletext,strlen(sampletext));
1062
+reui_balloon(re->ui, 's', re->x+re->w/2, re->y+re->h-1, "\xff\x00\x00\x80", "\xff\xff\xff\xaf", "}",1);
1063
+reui_balloon(re->ui, 'e', re->x+re->w-1,re->y+re->h/2, "\xff\x00\x00\x80", "\xff\xff\xff\xaf", "[",1);
1064
+reui_balloon(re->ui, 'w', re->x, re->y+re->h/2, "\xff\x00\x00\x80", "\xff\xff\xff\xaf", "]",1);
1065
+if((re->curline-re->originline)>=(re->maxrow/2))
1066
+        reui_balloon(re->ui, '\0', re->x+re->w/2, re->y+re->ui->fontheight*3/2, "\x80\x80\x80\xff", "\xff\xff\xff\xcf",sampletextlarge,strlen(sampletextlarge));
1067
+else
1068
+        reui_balloon(re->ui, '\0', re->x+re->w/2, re->y+re->h-re->ui->fontheight*3/2, "\x80\x80\x80\xff", "\xff\xff\xff\xcf",sampletextlarge,strlen(sampletextlarge));
1069
+}
1070
+#endif
1056 1071
         return(0);
1057 1072
 }
1058 1073