@ -6,6 +6,95 @@ ncplane* ncvisual_plane(ncvisual* ncv){
return ncv - > ncp ;
}
// alpha comes to us 0--255, but we have only 3 alpha values to map them to.
// settled on experimentally.
static inline bool
ffmpeg_trans_p ( bool bgr , unsigned char alpha ) {
if ( ! bgr & & alpha < 192 ) {
return true ;
}
return false ;
}
// RGBA/BGRx blitter. For incoming BGRx (no transparency), bgr == true.
static inline int
tria_blit ( ncplane * nc , int placey , int placex , int linesize , const void * data ,
int begy , int begx , int leny , int lenx , bool bgr ) {
const int bpp = 32 ;
const int rpos = bgr ? 2 : 0 ;
const int bpos = bgr ? 0 : 2 ;
int dimy , dimx , x , y ;
int visy = begy ;
int total = 0 ; // number of cells written
ncplane_dim_yx ( nc , & dimy , & dimx ) ;
// FIXME not going to necessarily be safe on all architectures hrmmm
const unsigned char * dat = data ;
for ( y = placey ; visy < ( begy + leny ) & & y < dimy ; + + y , visy + = 2 ) {
if ( ncplane_cursor_move_yx ( nc , y , placex ) ) {
return - 1 ;
}
int visx = begx ;
for ( x = placex ; visx < ( begx + lenx ) & & x < dimx ; + + x , + + visx ) {
const unsigned char * rgbbase_up = dat + ( linesize * visy ) + ( visx * bpp / CHAR_BIT ) ;
const unsigned char * rgbbase_down = dat + ( linesize * ( visy + 1 ) ) + ( visx * bpp / CHAR_BIT ) ;
//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]);
cell * c = ncplane_cell_ref_yx ( nc , y , x ) ;
// use the default for the background, as that's the only way it's
// effective in that case anyway
c - > channels = 0 ;
c - > attrword = 0 ;
if ( ffmpeg_trans_p ( bgr , rgbbase_up [ 3 ] ) | | ffmpeg_trans_p ( bgr , rgbbase_down [ 3 ] ) ) {
cell_set_bg_alpha ( c , CELL_ALPHA_TRANSPARENT ) ;
if ( ffmpeg_trans_p ( bgr , rgbbase_up [ 3 ] ) & & ffmpeg_trans_p ( bgr , rgbbase_down [ 3 ] ) ) {
cell_set_fg_alpha ( c , CELL_ALPHA_TRANSPARENT ) ;
} else if ( ffmpeg_trans_p ( bgr , rgbbase_up [ 3 ] ) ) { // down has the color
if ( cell_load ( nc , c , " \u2584 " ) < = 0 ) { // lower half block
return - 1 ;
}
cell_set_fg_rgb ( c , rgbbase_down [ rpos ] , rgbbase_down [ 1 ] , rgbbase_down [ bpos ] ) ;
} else { // up has the color
if ( cell_load ( nc , c , " \u2580 " ) < = 0 ) { // upper half block
return - 1 ;
}
cell_set_fg_rgb ( c , rgbbase_up [ rpos ] , rgbbase_up [ 1 ] , rgbbase_up [ bpos ] ) ;
}
} else {
if ( memcmp ( rgbbase_up , rgbbase_down , 3 ) = = 0 ) {
cell_set_fg_rgb ( c , rgbbase_down [ rpos ] , rgbbase_down [ 1 ] , rgbbase_down [ bpos ] ) ;
cell_set_bg_rgb ( c , rgbbase_down [ rpos ] , rgbbase_down [ 1 ] , rgbbase_down [ bpos ] ) ;
if ( cell_load ( nc , c , " " ) < = 0 ) { // only need the background
return - 1 ;
}
} else {
cell_set_fg_rgb ( c , rgbbase_up [ rpos ] , rgbbase_up [ 1 ] , rgbbase_up [ bpos ] ) ;
cell_set_bg_rgb ( c , rgbbase_down [ rpos ] , rgbbase_down [ 1 ] , rgbbase_down [ bpos ] ) ;
if ( cell_load ( nc , c , " \u2580 " ) < = 0 ) { // upper half block
return - 1 ;
}
}
}
+ + total ;
}
}
return total ;
}
// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset
// from the upper left by 'placey' and 'placex'. Each row ought occupy
// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A
// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'.
int ncblit_bgrx ( ncplane * nc , int placey , int placex , int linesize ,
const void * data , int begy , int begx , int leny , int lenx ) {
return tria_blit ( nc , placey , placex , linesize , data ,
begy , begx , leny , lenx , true ) ;
}
int ncblit_rgba ( ncplane * nc , int placey , int placex , int linesize ,
const void * data , int begy , int begx , int leny , int lenx ) {
return tria_blit ( nc , placey , placex , linesize , data ,
begy , begx , leny , lenx , false ) ;
}
void ncvisual_destroy ( ncvisual * ncv ) {
if ( ncv ) {
# ifdef USE_FFMPEG
@ -354,95 +443,6 @@ ncvisual* ncvisual_open_plane(notcurses* nc, const char* filename,
return ncv ;
}
// alpha comes to us 0--255, but we have only 3 alpha values to map them to.
// settled on experimentally.
static inline bool
ffmpeg_trans_p ( bool bgr , unsigned char alpha ) {
if ( ! bgr & & alpha < 192 ) {
return true ;
}
return false ;
}
// RGBA/BGRx blitter. For incoming BGRx (no transparency), bgr == true.
static inline int
tria_blit ( ncplane * nc , int placey , int placex , int linesize , const void * data ,
int begy , int begx , int leny , int lenx , bool bgr ) {
const int bpp = 32 ;
const int rpos = bgr ? 2 : 0 ;
const int bpos = bgr ? 0 : 2 ;
int dimy , dimx , x , y ;
int visy = begy ;
int total = 0 ; // number of cells written
ncplane_dim_yx ( nc , & dimy , & dimx ) ;
// FIXME not going to necessarily be safe on all architectures hrmmm
const unsigned char * dat = data ;
for ( y = placey ; visy < ( begy + leny ) & & y < dimy ; + + y , visy + = 2 ) {
if ( ncplane_cursor_move_yx ( nc , y , placex ) ) {
return - 1 ;
}
int visx = begx ;
for ( x = placex ; visx < ( begx + lenx ) & & x < dimx ; + + x , + + visx ) {
const unsigned char * rgbbase_up = dat + ( linesize * visy ) + ( visx * bpp / CHAR_BIT ) ;
const unsigned char * rgbbase_down = dat + ( linesize * ( visy + 1 ) ) + ( visx * bpp / CHAR_BIT ) ;
//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]);
cell * c = ncplane_cell_ref_yx ( nc , y , x ) ;
// use the default for the background, as that's the only way it's
// effective in that case anyway
c - > channels = 0 ;
c - > attrword = 0 ;
if ( ffmpeg_trans_p ( bgr , rgbbase_up [ 3 ] ) | | ffmpeg_trans_p ( bgr , rgbbase_down [ 3 ] ) ) {
cell_set_bg_alpha ( c , CELL_ALPHA_TRANSPARENT ) ;
if ( ffmpeg_trans_p ( bgr , rgbbase_up [ 3 ] ) & & ffmpeg_trans_p ( bgr , rgbbase_down [ 3 ] ) ) {
cell_set_fg_alpha ( c , CELL_ALPHA_TRANSPARENT ) ;
} else if ( ffmpeg_trans_p ( bgr , rgbbase_up [ 3 ] ) ) { // down has the color
if ( cell_load ( nc , c , " \u2584 " ) < = 0 ) { // lower half block
return - 1 ;
}
cell_set_fg_rgb ( c , rgbbase_down [ rpos ] , rgbbase_down [ 1 ] , rgbbase_down [ bpos ] ) ;
} else { // up has the color
if ( cell_load ( nc , c , " \u2580 " ) < = 0 ) { // upper half block
return - 1 ;
}
cell_set_fg_rgb ( c , rgbbase_up [ rpos ] , rgbbase_up [ 1 ] , rgbbase_up [ bpos ] ) ;
}
} else {
if ( memcmp ( rgbbase_up , rgbbase_down , 3 ) = = 0 ) {
cell_set_fg_rgb ( c , rgbbase_down [ rpos ] , rgbbase_down [ 1 ] , rgbbase_down [ bpos ] ) ;
cell_set_bg_rgb ( c , rgbbase_down [ rpos ] , rgbbase_down [ 1 ] , rgbbase_down [ bpos ] ) ;
if ( cell_load ( nc , c , " " ) < = 0 ) { // only need the background
return - 1 ;
}
} else {
cell_set_fg_rgb ( c , rgbbase_up [ rpos ] , rgbbase_up [ 1 ] , rgbbase_up [ bpos ] ) ;
cell_set_bg_rgb ( c , rgbbase_down [ rpos ] , rgbbase_down [ 1 ] , rgbbase_down [ bpos ] ) ;
if ( cell_load ( nc , c , " \u2580 " ) < = 0 ) { // upper half block
return - 1 ;
}
}
}
+ + total ;
}
}
return total ;
}
// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset
// from the upper left by 'placey' and 'placex'. Each row ought occupy
// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A
// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'.
int ncblit_bgrx ( ncplane * nc , int placey , int placex , int linesize ,
const void * data , int begy , int begx , int leny , int lenx ) {
return tria_blit ( nc , placey , placex , linesize , data ,
begy , begx , leny , lenx , true ) ;
}
int ncblit_rgba ( ncplane * nc , int placey , int placex , int linesize ,
const void * data , int begy , int begx , int leny , int lenx ) {
return tria_blit ( nc , placey , placex , linesize , data ,
begy , begx , leny , lenx , false ) ;
}
int ncvisual_render ( const ncvisual * ncv , int begy , int begx , int leny , int lenx ) {
//fprintf(stderr, "render %dx%d+%dx%d\n", begy, begx, leny, lenx);
if ( begy < 0 | | begx < 0 | | lenx < - 1 | | leny < - 1 ) {
@ -610,6 +610,7 @@ char* ncvisual_subtitle(const ncvisual* ncv){
int ncvisual_init ( int loglevel ) {
( void ) loglevel ;
return 0 ;
return 0 ; // allow success here
}
# endif