Go Back   Cockos Incorporated Forums > REAPER Forums > ReaScript, JSFX, REAPER Plug-in Extensions, Developer Forum

Reply
 
Thread Tools Display Modes
Old 05-03-2019, 04:59 PM   #1
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,902
Default Q: Text Alignement in Video Processor (Split multiline string with EEL?)

Hi,


For having subtitles in video processor, we would need to center multiline text. FOr that, each line have to break and center separatly.



Problem : How would you split multines strings at new line (\n) ?


Trick parts are managing different number of lines (from 0 to more)


Here what I came up so far.


Code:
window_w = 640;
window_h = 270;

project_w = 640;

function init(window_w, window_h) (
  gfx_init("GFX" , window_w, window_h);
);

function Update() (
  
  #text="What do you think of that?\nAwesome"; // set to string to override
  match("%s\n%s",#text, #line1, #line2 );

  gfx_r = 1;
  
  gfx_measurestr(#line1,txtw,txth);
  gfx_x = (project_w-txtw)/2;
  gfx_printf(#line1);
  
  gfx_measurestr(#line2,txtw,txth);
  gfx_x = (project_w-txtw)/2;
  gfx_y = gfx_y + txth;
  gfx_printf(#line2);
  
  gfx_update();
  defer("run");
);

function run() (

  Update()

);

init(window_w, window_h);
run();

This EEL code action (easier to debug than video processor) only works if the lines have exactly one line break.


Doesnt work for more, or doesn't work for none.


How would you make it work with a uncertain number of line breaks ?


Cheers !

Last edited by X-Raym; 05-03-2019 at 10:37 PM.
X-Raym is offline   Reply With Quote
Old 05-03-2019, 05:24 PM   #2
cfillion
Human being with feelings
 
cfillion's Avatar
 
Join Date: May 2015
Location: Québec, Canada
Posts: 4,970
Default

gfx_drawstr supports centering multiline strings:

Code:
#text = "What do you think of that?\nAwesome";

ALIGN_CENTER_HORIZONTAL  = 1<<0;
ALIGN_JUSTIFY_RIGHT      = 1<<1;
ALIGN_CENTER_VERTICAL    = 1<<2;
ALIGN_JUSTIFY_BOTTOM     = 1<<3;
IGNORE_RIGHT_BOTTOM      = 1<<8;

function update() (  
  gfx_x = gfx_y = 0;
  gfx_drawstr(#text, ALIGN_CENTER_HORIZONTAL, gfx_w, gfx_h);

  gfx_update();
  gfx_getchar() >= 0 ? defer("update()");
);

gfx_init("", 720, 100);
update();

Last edited by cfillion; 05-03-2019 at 05:32 PM.
cfillion is offline   Reply With Quote
Old 05-03-2019, 10:37 PM   #3
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,902
Default

@cfillion
Oh excellent ! I didn't knew that



The problem is... gfx_drawstr isn't accessible via Video Processor. :S
There is only gfx_str_draw and it doesn't have alignement. Only pos and color.



Code:
gfx_str_draw(#string[,x,y,fxc_r,fxc_g,fxc_b])
Draw string, fxc_r/g/b are the FX color if Shadow/Outline are set in the font

And alignement trick you shew doesn't work for this function :/
X-Raym is offline   Reply With Quote
Old 11-17-2022, 06:10 AM   #4
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,902
Default

I guess this would need some kind a loop to split a each \n character... I wish STR manipulaiton in EEL where more easy ^^
X-Raym is offline   Reply With Quote
Old 11-21-2022, 02:20 PM   #5
Fabian
Human being with feelings
 
Fabian's Avatar
 
Join Date: Sep 2008
Location: Sweden
Posts: 7,433
Default

Quote:
Originally Posted by X-Raym View Post
I guess this would need some kind a loop to split a each \n character... I wish STR manipulaiton in EEL where more easy ^^
Try this:
Code:
window_w = 640;
window_h = 270;

project_w = 640;

function init(window_w, window_h) (
  gfx_init("GFX" , window_w, window_h);
);

function pstring(str)
(
  gfx_measurestr(str, txtw, txth);
  gfx_x = (project_w-txtw)/2;
  gfx_printf(str);
  txth; // return text height
);

function domatch(fmt, txt)
(
  ptr = 0;
  strcpy(ptr, txt);
  count = 0;
  while
  (
    retval = match(fmt, ptr, ptr+2, ptr+1);
    ptr += 2;
    count += 1;
    retval;
  );
  strcpy(ptr-1, ptr-2);
  count; // return number of strings
);

function Update() (
  
  #fmt = "%s\n%s";
  #text="What do You think of that?\nAwesome!\nRight?"; // set to string to override
  // match("%s\n%s",#text, #line1, #line2 ); // matches the LAST \n (not the first)
  count = domatch(#fmt, #text);

  gfx_r = 1;
  gfx_y = 0;
  
  loop(count,
    gfx_y += pstring(2*count-1);
    count -= 1;
  );

  gfx_update();
  defer("run");
);

function run() (

  Update()

);

init(window_w, window_h);
run();
When I try different numbers (including zero) of \n in the text string, I get what I expect. The strings are returned in reverse order in odd numbered slots. The return value of match is undocumented, but it seems to return 1 when a match is found, else 0, which makes sense. The code in bold is what I added to the original code in posting #1. The strcpy before domatch returns copies the last string into the proper odd numbered slot.
__________________
// MVHMF
I never always did the right thing, but all I did wasn't wrong...
Fabian is offline   Reply With Quote
Old 11-21-2022, 05:39 PM   #6
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,902
Default

@Fabian
Hi, thanks for your attempt !


This doesnt seems to be compatible with video processor unfortunately, even when converting to gfx function from video processor


https://gist.github.com/X-Raym/516df...7ab2421bc9d2c7


It is more complex with video processor cause with have less function and less debug feature.


If would be so more handy if it was just a flag to gfx_str_draw like in the reascript equivalent.
X-Raym is offline   Reply With Quote
Old 11-22-2022, 06:31 AM   #7
DarkStar
Human being with feelings
 
DarkStar's Avatar
 
Join Date: May 2006
Location: Surrey, UK
Posts: 19,681
Default

I find that using \n to start a new line can leave quite a gap vertically, so I put together my own JS FX function.

It takes a string and the width available (in pixels) and displays a multi-line label, each line centrally-aligned, with line breaks triggered by \ (no n needed) or by a space character:



You might find it useful. Any improvements would be appreciated.

Code:
// ------------------------------------------------
function print_one_line(PLCX)     // uses #line_out
// ------------------------------------------------
local (Lheight Lchar_width Lwidth Lchar_width Llabel_len )
// .... PLCX is the centre position of the line, in pixels
(
    Llabel_len = strlen(#line_out);
    gfx_measurestr(#line_out, Lwidth, Lheight);
    Lchar_width = Lwidth / Llabel_len;
    gfx_x = PLCX - strlen(#line_out) * Lchar_width/2;

    gfx_drawstr(#line_out);
    #line_out = "";
    space_idx = EMPTY;
    gfx_getfont() +1 == 0 ? gfx_y +=(Lheight+3)
                          : gfx_y +=(Lheight-4);

); // .... end of function


// ------------------------------------------------
function print_string_to_label (Pstr_idx, Pline_length)
// ------------------------------------------------
// .... Pline_length is in pixels

local ( Lwhite_space Lback_slash Llabel_len Lout_idx Lnoof_lines
        Lsave_gfxx Lsave_gfxy Lin_idx Lend_idx Lone_char LCX LW LH )
(
    EMPTY = -1;
    Lwhite_space = $' ';
    Lback_slash  = $'\';
    LW = 0; LH = 0; Lnoof_lines =0;

    Lsave_gfxx = gfx_x;
    LCX        = gfx_x; // centre position
    Lsave_gfxy = gfx_y;

    Llabel_len = strlen(Pstr_idx);
    Lin_idx = 0;
    Lend_idx = Llabel_len -1;
    space_idx = EMPTY;
    Lout_idx = 0;
    #line_out = "";
    
    while (Lin_idx < Llabel_len) (
        Lone_char = str_getchar(Pstr_idx, Lin_idx);

        Lone_char == Lback_slash ? (
            print_one_line(LCX);
            Lnoof_lines +=1;
            Lout_idx=0;
        ):(
        Lone_char == Lwhite_space ? (
            str_setchar(#line_out, Lout_idx, Lone_char);
            space_idx = Lout_idx;
        );

        gfx_measurestr(#line_out, LW, LH);
        LW > Pline_length +14 *Gscale * Gtext_scale ? (
            space_idx > EMPTY ? (
                strcpy(#out_save,#line_out);
                strcpy_substr(#line_out,#line_out,0,space_idx); 
                space_idx_save = space_idx;
                print_one_line(LCX);
                Lnoof_lines +=1;
                strcpy_substr(#line_out,#out_save,space_idx_save+1);
            ):(
                strcpy(#out_save,#line_out);
                strcpy_substr(#line_out,#out_save,0,Lout_idx -1); // first N characters
                print_one_line(LCX);
                Lnoof_lines +=1;
                strcpy_substr(#line_out, #out_save, Lout_idx-1,1);
            );
            Lout_idx = strlen(#line_out);
            Lin_idx -=1;
        ):(

        Lin_idx >= Llabel_len-1 ? (
            str_setchar(#line_out, Lout_idx, Lone_char); 
            print_one_line(LCX); 
            Lnoof_lines +=1;
        ):(
            str_setchar(#line_out, Lout_idx, Lone_char);
            Lout_idx +=1;
        ); ); ); 

        Lin_idx +=1;
    ); // .... end of while ()

// -------------------
    gfx_x = Lsave_gfxx;
    gfx_y = Lsave_gfxy;

Lnoof_lines; 
); // .... end of function
__________________
DarkStar ... interesting, if true. . . . Inspired by ...

Last edited by DarkStar; 11-22-2022 at 09:25 AM. Reason: added: EMPTY = -1;
DarkStar is offline   Reply With Quote
Old 11-22-2022, 06:34 AM   #8
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,902
Default

@DarkStar
Looks good but not sure it is portable to Video Processor.


Video Processor use EEL-like syntax but as a different set of functions and works a bit differently on some api subset (GFX).

Thx for sharing anyway 😉
X-Raym is offline   Reply With Quote
Old 11-22-2022, 11:45 AM   #9
Fabian
Human being with feelings
 
Fabian's Avatar
 
Join Date: Sep 2008
Location: Sweden
Posts: 7,433
Default

Quote:
Originally Posted by X-Raym View Post
@Fabian
Hi, thanks for your attempt !

This doesnt seems to be compatible with video processor unfortunately, even when converting to gfx function from video processor
I'm not sure what you mean, this works for me as video processor preset (Reaper v6.70, Win7):
Code:
input = 0;
project_wh_valid===0 ? input_info(input, project_w, project_h);
gfx_y = 0;

gfx_set(0, 0, 0, 1);
gfx_fillrect(0, 0, project_w, project_h);
gfx_set(1, 1, 1, 1);

function printc(str)
(
  gfx_str_measure(str, txtw, txth);
  gfx_x = (project_w - txtw)/2;
  gfx_str_draw(str, gfx_x, gfx_y);
  txth; // return text height
);

function dosplit(fmt, txt)
(
  ptr = 0;
  strcpy(ptr, txt);
  count = 0;
  while
  (
    retval = match(fmt, ptr, ptr+2, ptr+1);
    ptr += 2;
    count += 1;
    retval;
  );
  strcpy(ptr-1, ptr-2);
  count; // return number of strings
);

#fmt = "%s\n%s";
#text="What do You think of that?\nAwesome!\nRight?\nRIGHT?!\n... or wrong.";
count = dosplit(#fmt, #text);

  loop(count,
    gfx_y += printc(2*count-1);
    count -= 1;
  );
I renamed the functions to printc and dosplit, as I think those are more appropriate names.
__________________
// MVHMF
I never always did the right thing, but all I did wasn't wrong...

Last edited by Fabian; 11-22-2022 at 11:51 AM.
Fabian is offline   Reply With Quote
Old 11-23-2022, 06:50 AM   #10
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,902
Default

@Fabian
Excellent ! Thank you very much !


I have created a ReaTeam Repo for video processors, and I have put your script in it.


https://github.com/ReaTeam/Video-Pro...ine%20text.eel


I also added few features in it like knobs for text size, vertical H, background, variable for font family
X-Raym is offline   Reply With Quote
Old 11-23-2022, 12:49 PM   #11
Fabian
Human being with feelings
 
Fabian's Avatar
 
Join Date: Sep 2008
Location: Sweden
Posts: 7,433
Default

Quote:
Originally Posted by X-Raym View Post
@Fabian
Excellent ! Thank you very much !


I have created a ReaTeam Repo for video processors, and I have put your script in it.


https://github.com/ReaTeam/Video-Pro...ine%20text.eel


I also added few features in it like knobs for text size, vertical H, background, variable for font family
OK, great!
__________________
// MVHMF
I never always did the right thing, but all I did wasn't wrong...
Fabian is offline   Reply With Quote
Old 11-29-2022, 11:52 AM   #12
X-Raym
Human being with feelings
 
X-Raym's Avatar
 
Join Date: Apr 2013
Location: France
Posts: 9,902
Default

I have released a companion script to feed the content of this processor with gmem content, pushed from text items under play/edit cursor. Aka, subtitles track for video processor!


https://forum.cockos.com/showpost.ph...1&postcount=49


Having it centered is definitely more elegant that my previous preset wich was simply left centered.




If one of the contributors here want it for free, just PM me :P



Cheers !
X-Raym is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 05:32 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.