14 #include <pango/pangocairo.h>
15 static int font_cmp(
const void *p1,
const void *p2);
19 static void fill_bckg(lives_painter_t *cr,
double x,
double y,
double dx,
double dy) {
27 static void getxypos(LingoLayout *layout,
int *px,
int *py,
int width,
int height,
boolean cent,
double *pw,
double *ph) {
38 lingo_layout_get_size(layout, &w_, &h_);
41 d = ((double)h_) / (double)LINGO_SCALE;
45 if (py) *py = height - (int) * ph;
47 d = ((double)w_) / (double)LINGO_SCALE;
50 if (px) *px = cent ? (width - (int)d) >> 1 : 0.;
54 static char *rewrap_text(
char *text) {
67 boolean needs_nl =
FALSE;
68 int numlines, maxline = -1;
71 if (!text || !(*text))
return NULL;
73 jtext = lives_strdup(
"");
75 lines = lives_strsplit(text,
"\n", numlines);
77 for (i = 0; i < numlines; i++) {
84 lives_strfreev(lines);
87 for (i = 0; i < numlines; i++) {
90 for (j = maxlen - 1; j > 0; j--) {
93 if (lines[i][j - 1] ==
' ') {
95 first = lives_strndup(lines[i], j);
97 second = lines[i] + j;
106 lines[i][maxlen - 1] = 0;
108 lives_snprintf(&lines[i][maxlen - 4], 4,
"%s",
"...");
113 lines[i][maxlen - 1] = 0;
115 lives_snprintf(&lines[i][maxlen - 4], 4,
"%s",
"...");
123 lives_strfreev(lines);
128 static char *remove_first_line(
char *text) {
131 for (i = 0; i < tlen; i++) {
132 if (text[i] ==
'\n')
return lives_strdup(text + i + 1);
138 static char *deparagraph(
char *text) {
141 int i, j = 0, nlcnt = 0;
143 for (i = 0; text[i]; i++) {
144 if (text[i] ==
'\n') {
145 if (!text[i + 1] || text[i + 1] ==
'\n') nlcnt++;
152 for (i = 0; text[i]; i++) {
153 xtext[j++] = text[i];
154 if (text[i] ==
'\n') {
155 if (!text[i + 1] || text[i + 1] ==
'\n') xtext[j++] =
' ';
166 lives_colRGBA64_t *bg,
int dwidth,
int dheight,
double x_bg,
double y_bg,
double x_text,
double y_text) {
170 if (bg) b_alpha = (double)bg->
alpha / 65535.;
171 if (fg) f_alpha = (double)fg->
alpha / 65535.;
177 lingo_layout_set_text(layout,
"", -1);
180 fill_bckg(cr, x_bg, y_bg, dwidth, dheight);
206 char *readytext, *testtext = NULL, *newtext = NULL, *tmp, *xx;
210 int w = 0, h = 0, pw;
215 boolean heightdone =
FALSE;
216 boolean needs_newline =
FALSE;
220 ctx = lives_widget_create_lingo_context(widget);
221 if (!ctx || !LINGO_IS_CONTEXT(ctx))
return NULL;
223 layout = lingo_layout_new(ctx);
224 if (!layout || !LINGO_IS_LAYOUT(layout)) {
229 readytext = lives_strdup(
"");
232 if (!msg)
return NULL;
234 if (
error != WEED_SUCCESS)
return NULL;
235 if (!newtext)
return NULL;
237 if (slen > 0 && newtext[slen - 1] ==
'\n') {
242 g_print(
"Got msg:%s\ntotal is now %d lines\n", newtext, totlines);
247 if (
error != WEED_SUCCESS)
return NULL;
258 if (
error != WEED_SUCCESS)
break;
262 g_print(
"Got msg:%s\ntotal is now %d lines\n", newtext, totlines);
267 if (
error != WEED_SUCCESS)
break;
273 needs_newline =
TRUE;
274 lingo_layout_set_text(layout,
"", -1);
276 layout = lingo_layout_new(ctx);
277 testtext = deparagraph(testtext);
278 lingo_layout_set_text(layout, testtext, -1);
279 lingo_layout_get_size(layout, &w, &h);
285 g_print(
"Sizes %d %d window, %d %d layout ()\n", width, height, w, h);
290 g_print(
"Too high !\n");
296 tmp = remove_first_line(newtext);
302 g_print(
"Retry with (%d) |%s|\n", totlines, newtext);
307 g_print(
"Testing with:%s:\n", testtext);
309 lingo_layout_set_text(layout,
"", -1);
311 layout = lingo_layout_new(ctx);
312 lingo_layout_set_width(layout, width * LINGO_SCALE);
313 testtext = deparagraph(testtext);
314 lingo_layout_set_text(layout, testtext, -1);
315 lingo_layout_get_size(layout, NULL, &h);
323 if (0 && w > width) {
324 int jumpval = 1, dirn = -1, tjump = 0;
328 g_print(
"Too wide !!!\n");
335 tjump = dirn * jumpval;
343 if (whint == 0 || whint + 4 > slen) {
344 xx = lives_strndup(newtext, slen + tjump);
346 xx = lives_strndup(newtext, whint + 4 + tjump);
348 tmp = rewrap_text(xx);
351 g_print(
"Retry with (%d) |%s|\n", totlines, xx);
355 lingo_layout_set_text(layout,
"", -1);
357 layout = lingo_layout_new(ctx);
359 tmp = deparagraph(tmp);
360 lingo_layout_set_text(layout, tmp, -1);
361 lingo_layout_get_size(layout, &pw, NULL);
362 w = pw / LINGO_SCALE;
366 if (whint <= 0 || (ll = (
int)
lives_strlen(tmp)) < whint) whint = ll;
379 g_print(
"Width OK now\n");
391 readytext = testtext;
394 g_print(
"|%s| passed size tests\n", readytext);
396 if (heightdone)
break;
403 if (linecount) *linecount = totlines;
406 g_print(
"|%s| FINAL !!\n", readytext);
418 char **font_list = NULL;
421 ctx = gdk_pango_context_get();
424 pfm = pango_context_get_font_map(ctx);
427 PangoFontFamily **pff = NULL;
428 pango_font_map_list_families(pfm, &pff, &num);
430 font_list = (
char **)
lives_malloc((num + 1) *
sizeof(
char *));
432 for (i = 0; i < num; ++i)
433 font_list[i] = lives_strdup(pango_font_family_get_name(pff[i]));
434 font_list[num] = NULL;
435 qsort(font_list, num,
sizeof(
char *), font_cmp);
445 QStringList qsl = qfd.families();
446 font_list = (
char **)
lives_malloc((qsl.size() + 1) *
sizeof(
char *));
447 for (i = 0; i < qsl.size(); i++) {
448 font_list[i] = lives_strdup(qsl.at(i).toUtf8().constData());
456 static int font_cmp(
const void *p1,
const void *p2) {
457 const char *s1 = (
const char *)(*(
char **)p1);
458 const char *s2 = (
const char *)(*(
char **)p2);
459 char *u1 = lives_utf8_casefold(s1, -1);
460 char *u2 = lives_utf8_casefold(s2, -1);
468 LingoLayout *
render_text_to_cr(LiVESWidget *widget, lives_painter_t *cr,
const char *text,
const char *fontname,
470 boolean center,
boolean rising,
double *top,
int *offs_x,
int dwidth,
int *dheight) {
482 LingoFontDescription *font = NULL;
485 int x_pos = 0, y_pos = 0;
486 double lwidth = (double)dwidth, lheight = (
double)(*dheight);
488 if (!cr)
return NULL;
492 LingoContext *ctx = gtk_widget_get_pango_context(widget);
493 layout = lingo_layout_new(ctx);
495 layout = pango_cairo_create_layout(cr);
496 if (!layout)
return NULL;
498 font = lingo_font_description_new();
499 pango_font_description_set_family(font, fontname);
500 pango_font_description_set_absolute_size(font, size * LINGO_SCALE);
501 pango_layout_set_font_description(layout, font);
504 lingo_layout_set_markup(layout, text, -1);
507 if (center) lingo_layout_set_alignment(layout, LINGO_ALIGN_CENTER);
508 else lingo_layout_set_alignment(layout, LINGO_ALIGN_LEFT);
510 getxypos(layout, &x_pos, &y_pos, dwidth, *dheight, center, &lwidth, &lheight);
511 if (lwidth > dwidth) {
512 lingo_layout_set_width(layout, dwidth * LINGO_SCALE);
515 lwidth = (double)dwidth;
516 lheight = (double)(*dheight);
517 getxypos(layout, &x_pos, &y_pos, dwidth, *dheight, center, &lwidth, &lheight);
520 if (!rising) y_pos = (double) * dheight * *top;
530 if (font) lingo_font_description_free(font);
537 layout_to_lives_painter(layout, cr, mode, fg, bg, lwidth, lheight, x_pos, y_pos, x_pos, y_pos);
544 if (!text)
return layer;
549 const char *font =
"Sans";
550 boolean fake_gamma =
FALSE;
564 weed_set_int_value(layer, WEED_LEAF_GAMMA_TYPE, WEED_GAMMA_LINEAR);
572 boolean center,
boolean rising,
double top) {
576 lives_painter_t *cr = NULL;
585 int lheight = height;
586 int gamma = WEED_GAMMA_UNKNOWN, offsx = 0;
600 if (ipsize == opsize) {
614 fg_col, bg_col, center, rising, &top, &offsx, width, &lheight);
620 if (top * height + lheight < height) {
622 boolean rbswapped =
FALSE;
626 xsrc = src + (int)(top * height) * row;
653 layout =
render_text_to_cr(NULL, cr, text, fontname, size, mode, fg_col, bg_col, center,
FALSE, &ztop, &offsx, width, &height);
654 if (layout && LINGO_IS_LAYOUT(layout)) {
655 lingo_painter_show_layout(cr, layout);
667 if (pd != xsrc)
lives_memcpy(src + (
int)(top * height) * row, pd, lheight * row);
685 if (!cr)
return layer;
686 layout =
render_text_to_cr(NULL, cr, text, fontname, size, mode, fg_col, bg_col, center, rising, &top, &offsx, width, &height);
687 if (layout && LINGO_IS_LAYOUT(layout)) {
688 lingo_painter_show_layout(cr, layout);
693 if (gamma != WEED_GAMMA_UNKNOWN)
698 static const char *cr_str =
"\x0D";
699 static const char *lf_str =
"\x0A";
710 if (fd < 0 || !title)
return NULL;
716 poslf = strstr(data, lf_str);
717 if (poslf) *poslf =
'\0';
718 poscr = strstr(data, cr_str);
719 if (poscr) *poscr =
'\0';
721 if (!ret) ret = lives_strdup(data);
723 char *tmp = lives_strconcat(ret,
"\n", data, NULL);
737 char *retmore = NULL;
739 size_t curlen, retlen;
741 if (fd < 0 || !title)
return NULL;
747 poslf = strstr(data, lf_str);
748 if (poslf) *poslf =
'\0';
749 poscr = strstr(data, cr_str);
750 if (poscr) *poscr =
'\0';
754 ret =
subst(data,
"[br]",
"\n");
755 if (!ret)
return NULL;
758 retmore =
subst(data,
"[br]",
"\n");
759 if (!retmore)
return NULL;
762 retlen += curlen + 1;
766 strcat(ret, retmore);
786 char *poslf = NULL, *poscr = NULL;
787 double starttime, endtime;
788 int hstart, mstart, sstart, fstart;
789 int hend, mend, send, fend;
807 poslf = strstr(data, lf_str);
810 poscr = strstr(data, cr_str);
815 i = sscanf(data,
"%d:%d:%d,%d --> %d:%d:%d,%d", \
816 &hstart, &mstart, &sstart, &fstart, \
817 &hend, &mend, &send, &fend);
820 starttime = hstart * 3600 + mstart * 60 + sstart + fstart / 1000.;
821 endtime = hend * 3600 + mend * 60 + send + fend / 1000.;
839 poslf = strstr(data, lf_str);
842 poscr = strstr(data, cr_str);
859 boolean starttext =
FALSE;
862 char *poslf = NULL, *poscr = NULL;
863 int hstart, mstart, sstart, fstart;
864 int hend, mend, send, fend;
866 double starttime, endtime;
868 if (!strncmp(data,
"[SUBTITLE]", 10)) {
873 if (!strncmp(data,
"[DELAY]", 7)) {
883 poslf = strstr(data, lf_str);
886 poscr = strstr(data, cr_str);
891 i = sscanf(data,
"%d:%d:%d.%d,%d:%d:%d.%d", \
892 &hstart, &mstart, &sstart, &fstart, \
893 &hend, &mend, &send, &fend);
896 starttime = hstart * 3600 + mstart * 60 + sstart + fstart / 100.;
897 endtime = hend * 3600 + mend * 60 + send + fend / 100.;
915 poslf = strstr(data, lf_str);
918 poscr = strstr(data, cr_str);
933 if (!sfile || !sfile->
subt)
return FALSE;
941 char *tmp = srt_read_text(sfile->
subt->
tfile, curr);
952 if (xtime < sfile->subt->first->start_time || xtime > sfile->
subt->
last->
end_time) {
960 if (xtime < curr->start_time && xtime <= curr->prev->end_time)
while (curr->
start_time > xtime) curr = curr->
prev;
966 char *tmp = srt_read_text(sfile->
subt->
tfile, curr);
978 if (!sfile->
subt)
return;
1000 if (!sfile)
return FALSE;
1019 static void parse_double_time(
double tim,
int *ph,
int *pmin,
int *psec,
int *pmsec,
int fix) {
1020 int ntim = (int)tim;
1024 m = (ntim - h * 3600) / 60;
1025 s = (ntim - h * 3600 - m * 60);
1026 if (fix == 3) ms = (int)((tim - ntim) * 1000.0 + .5);
1027 else ms = (int)((tim - ntim) * 100.0 + .5);
1041 int64_t savepos = 0;
1045 if (!sfile)
return FALSE;
1047 if (!subt)
return FALSE;
1055 if (fd < 0)
return FALSE;
1061 text = srt_read_text(subt->
tfile, ptr);
1069 if (dtim < start_time) dtim = start_time;
1070 dtim += offset_time;
1072 parse_double_time(dtim, &h, &m, &s, &ms, 3);
1076 if (dtim > end_time) dtim = end_time;
1077 dtim += offset_time;
1079 parse_double_time(dtim, &h, &m, &s, &ms, 3);
1085 }
else if (ptr->
start_time >= end_time)
break;
1103 int64_t savepos = 0;
1119 if (fd < 0)
return FALSE;
1135 char *br_text = NULL;
1137 text = sub_read_text(subt->
tfile, ptr);
1142 if (text[ll] ==
'\n') text[ll] = 0;
1144 br_text =
subst(text,
"\n",
"[br]");
1149 if (dtim < start_time) dtim = start_time;
1150 dtim += offset_time;
1152 parse_double_time(dtim, &h, &m, &s, &ms, 2);
1156 if (dtim > end_time) dtim = end_time;
1157 dtim += offset_time;
1159 parse_double_time(dtim, &h, &m, &s, &ms, 2);
1167 }
else if (ptr->
start_time >= end_time)
break;
1183 char **style,
char **weight) {
1184 if (!
string)
return FALSE;
1187 char **array = lives_strsplit(
string,
" ", numtok);
1191 for (
int i = 0; i < numtok - 1; i++) {
1197 }
else *font = lives_strdup(array[i]);
1200 if (size && numtok > 1 && atoi(array[numtok - 1])) *size = atoi(array[numtok - 1]);
1201 if (font && !atoi(array[numtok - 1])) {
1206 }
else *font = lives_strdup(array[numtok - 1]);
1208 lives_strfreev(array);