BitmapToolkit Scol plugin
BitmapToolkitText.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2015 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
25#include <algorithm>
26#include "freetypeFont.h"
27#include "Prerequisites.h"
28#include "BitmapToolkitText.h"
29#include "ScolConvert.h"
30
38// btfonts
39bool btfonts::initialized = false;
40std::map<std::string, btfonts::type> btfonts::font_to_cv;
41btfonts::type& btfonts::get(std::string name)
42{
43 if (!initialized)
44 initialize();
45 return font_to_cv[name];
46}
47
49{
50 font_to_cv["arial"] = type(BT_FONT_SANS);
51 font_to_cv["arial black"] = type(BT_FONT_SANS, true, true, false);
52 font_to_cv["helvetica"] = type(BT_FONT_SANS);
53 font_to_cv["calibri"] = type(BT_FONT_SANS);
54 font_to_cv["system"] = type(BT_FONT_SANS);
55 font_to_cv["times new roman"] = type(BT_FONT_SERIF);
56 font_to_cv["times"] = type(BT_FONT_SERIF);
57 font_to_cv["georgia"] = type(BT_FONT_SERIF);
58 font_to_cv["sans"] = type(BT_FONT_SANS);
59 font_to_cv["serif"] = type(BT_FONT_SERIF);
60 font_to_cv["script"] = type(BT_FONT_SCRIPT);
61}
62
63bool btfonts::has(std::string name)
64{
65 return font_to_cv.count(name) != 0;
66}
68
69// CV font destruction callback
70int destroyCVFont(mmachine m, SCOL_PTR_TYPE handsys, int obj)
71{
72 PtrObjBTFont obj_font = MMgetPointer<PtrObjBTFont>(m, MTOP(obj));
73 if (obj_font)
74 SAFE_DELETE(obj_font);
75
76 MMsetPointer<PtrObjBTFont>(m, MTOP(obj), 0);
77
78 MMechostr(MSKDEBUG, "ObjBTFont destroyed.\n");
79 return 0;
80}
81
82std::string ReplaceAll(std::string str, const std::string& from, const std::string& to)
83{
84 size_t start_pos = 0;
85 while ((start_pos = str.find(from, start_pos)) != std::string::npos)
86 {
87 str.replace(start_pos, from.length(), to);
88 start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
89 }
90 return str;
91}
92
93// Takes a text as input, with opencv font parameters, and spits back lines within <max_width>
94std::vector<std::string> word_wrap(std::string input, PtrObjBTFont obj_font, int max_width, int splitlines)
95{
96 // Split text into words
97 std::vector<std::vector<std::string> > words;
98 max_width = std::max(max_width, 1);
99
100 // Clean text, replace all newlines to \n
101 input = ReplaceAll(input, "\r\n", "\n");
102 input = ReplaceAll(input, "\r", "\n");
103 std::istringstream is_line(input);
104 std::string line;
105
106 while (getline(is_line, line, '\n'))
107 {
108 words.push_back(std::vector<std::string>());
109 std::istringstream is_word(line);
110 std::string word;
111 while (getline(is_word, word, ' '))
112 {
113 word = ReplaceAll(word, "\t", " ");
114 words.back().push_back(word);
115 }
116 }
117
118 std::vector<std::string> output;
119
120 for (unsigned line_index = 0; line_index < words.size(); line_index++)
121 {
122 bool done = false;
123 unsigned int word_index = 0;
124 if (splitlines)
125 {
126 while (!done)
127 {
128 std::string text_line = "";
129 cv::Size line_size;
130 unsigned int local_word_index = word_index;
131 unsigned int word_count = 0;
132
133 // stack words until it gets wider than max_width
134 while (line_size.width <= max_width)
135 {
136 // there's no more words, text and line is over
137 if (local_word_index >= words[line_index].size())
138 {
139 done = true;
140 break;
141 }
142
143 if (word_count == 0)
144 text_line += words[line_index][local_word_index];
145 else
146 text_line += " " + words[line_index][local_word_index];
147
148#ifdef BT_USE_FREETYPE
149 if (obj_font->mode)
150 line_size = obj_font->ft2->getTextSize(text_line, obj_font->size, obj_font->thickness, NULL);
151 else
152#endif
153 line_size = cv::getTextSize(text_line, obj_font->face, obj_font->scale, obj_font->thickness, NULL);
154
155 local_word_index++; // goto next word
156 word_count++;
157 }
158
159
160 if (local_word_index >= words[line_index].size() && (words[line_index].size() <= 1))
161 done = true;
162
163 // revert to last word and trailing space if text is not done
164 if (!done && word_count > 1)
165 {
166 word_index = local_word_index - 1;
167 text_line = text_line.substr(0, text_line.length() - words[line_index][local_word_index - 1].length() - 1);
168 }
169 else
170 {
171 word_index++;
172 text_line = text_line.substr(0, text_line.length());
173 }
174
175 output.push_back(text_line);
176 }
177 }
178 else
179 {
180 std::string text_line = "";
181 unsigned int local_word_index = word_index;
182 unsigned int word_count = 0;
183
184 // stack words until it gets wider than max_width
185 while (local_word_index < words[line_index].size())
186 {
187 if (word_count == 0)
188 text_line += words[line_index][local_word_index];
189 else
190 text_line += " " + words[line_index][local_word_index];
191
192 local_word_index++; // goto next word
193 word_count++;
194 }
195
196 word_index++;
197 text_line = text_line.substr(0, text_line.length());
198
199 output.push_back(text_line);
200 }
201 }
202 return output;
203}
204
216int _CRBTfont(mmachine m)
217{
218 int ilineoffset = MMpull(m);
219 int iflags = MMpull(m);
220 int isize = MMpull(m);
221 int iface = MMpull(m);
222
223 // Defaults (everything is defaulted)
224 // ------------
225 std::string font_name = "";
226 int scol_font_face = BT_FONT_SANS;
227 int scol_font_flags = BT_FONT_ANTIALIAS | BT_FONT_FILLED;
228 int scol_font_size = 16;
229
230 PtrObjBTFont font = new ObjBTFont();
231
232 // Parse args
233 // ------------
234 if (iface != NIL)
235 font_name = MMstartstr(m, MTOP(iface));
236
237 if (isize != NIL)
238 scol_font_size = MTOI(isize);
239
240 if (iflags != NIL)
241 scol_font_flags = MTOI(iflags);
242
243 if (ilineoffset != NIL)
244 font->lineOffset = MTOF(ilineoffset) + 0.4f;
245
246 // Opencv font selection
247 // --------------------
248 std::transform(font_name.begin(), font_name.end(), font_name.begin(), ::tolower);
249 if (btfonts::has(font_name))
250 scol_font_face = btfonts::get(font_name).face;
251 switch (scol_font_face)
252 {
253 case BT_FONT_SANS:
254 {
255 if (scol_font_flags & BT_FONT_BOLD)
256 font->face = cv::FONT_HERSHEY_DUPLEX;
257 else
258 font->face = cv::FONT_HERSHEY_SIMPLEX;
259 }
260 break;
261 case BT_FONT_SERIF:
262 {
263 if (scol_font_flags & BT_FONT_BOLD)
264 font->face = cv::FONT_HERSHEY_TRIPLEX;
265 else
266 font->face = cv::FONT_HERSHEY_COMPLEX;
267 }
268 break;
269 case BT_FONT_SCRIPT:
270 {
271 if (scol_font_flags & BT_FONT_BOLD)
272 font->face = cv::FONT_HERSHEY_SCRIPT_COMPLEX;
273 else
274 font->face = cv::FONT_HERSHEY_SCRIPT_SIMPLEX;
275 }
276 break;
277 default:
278 font->face = cv::FONT_HERSHEY_SIMPLEX;
279 break;
280 }
281
282 // Other parameters
283 // ------------
284 if (scol_font_flags & BT_FONT_ITALIC)
285 font->face |= cv::FONT_ITALIC;
286
287 if (scol_font_flags & BT_FONT_ANTIALIAS)
288 font->linetype = cv::LINE_AA;
289 else
290 font->linetype = 8;
291
292 // Font scale
293 // ------------
294 cv::Size cv_font_size = cv::getTextSize(BT_CHARSETREF, font->face, 1.0, 1, NULL);
295 font->scale = ((float)scol_font_size / (float)cv_font_size.height);
296
297 font->size = scol_font_size;
298
299 // xoffset
300 switch (scol_font_face)
301 {
302 case BT_FONT_SANS:
303 {
304 font->xoffset = 2;
305 }
306 break;
307 case BT_FONT_SERIF:
308 {
309 font->xoffset = 2;
310 if (scol_font_flags & BT_FONT_ITALIC)
311 font->xoffset = (int)(font->scale * 2.0f) + 2;
312 }
313 break;
314 case BT_FONT_SCRIPT:
315 {
316 font->xoffset = (int)(font->scale * 4.0f) + 2;
317 }
318 break;
319 default:
320 break;
321 }
322
323 if (btfonts::get(font_name).bold)
324 {
325 font->thickness += 1;
326 if (btfonts::get(font_name).extra_bold)
327 font->thickness += 1;
328 }
329
330 if (!(scol_font_flags & BT_FONT_HOLLOW))
331 {
332 font->thickness += (int)((font->scale * 1.55f) - 1.0f);
333 }
334
335 font->thickness = std::max(1, font->thickness);
336
337 if (btfonts::get(font_name).italic)
338 font->face |= cv::FONT_ITALIC;
339
340 font->baseSize = cv::getTextSize(BT_CHARSET, font->face, font->scale, font->thickness, NULL);
341
342 // Store to tuple
343 // ----------------
344 if ((MMpushPointer(m, font) != 0))
345 {
346 if (font)
347 SAFE_DELETE(font);
348 MMset(m, 0, NIL);
349 return MERRMEM;
350 }
351
352 return OBJcreate(m, SObjBTFont, SCOL_PTR font, NIL, 0);
353}
354
366int _CRBTfontFromFile(mmachine m)
367{
368 int ilineoffset = MMpull(m);
369 int iflags = MMpull(m);
370 int isize = MMpull(m);
371 int ipath = MMpull(m);
372
373 if (ipath == NIL)
374 {
375 MMset(m, 0, NIL);
376 return 0;
377 }
378
379#ifndef BT_USE_FREETYPE
380
381 MMset(m, 0, NIL);
382 return 0;
383
384#else
385
386 // Defaults (everything is defaulted)
387 // ------------
388 int scol_font_flags = BT_FONT_ANTIALIAS | BT_FONT_FILLED;
389 int scol_font_size = 16;
390
391 PtrObjBTFont font = new ObjBTFont(1);
392
393 if (isize != NIL)
394 scol_font_size = MTOI(isize);
395
396 if (iflags != NIL)
397 scol_font_flags = MTOI(iflags);
398
399 if (ilineoffset != NIL)
400 font->lineOffset = MTOF(ilineoffset) + 0.4f;
401
402 // Parse args
403 // ------------
404 boost::filesystem::path fontPathBase = MMstartstr(m, MTOP(ipath));
405
406 //bool found = false;
407 //int index = ((scol_font_flags & BT_FONT_BOLD) && (scol_font_flags & BT_FONT_ITALIC)) ? 3 : (scol_font_flags & BT_FONT_ITALIC) ? 2 : (scol_font_flags & BT_FONT_BOLD) ? 1 : 0;
408 //if (index != 0)
409 //{
410 // if (!font->ft2->loadFontData(fontPathBase.generic_string(), index))
411 // {
412 // MMechostr(MSKDEBUG, "Warning on _CRBTfontFromFile : %s, not face for flags", fontPathBase.generic_string().c_str());
413 // index = 0;
414 // }
415 // else
416 // found = true;
417 //}
418 //
419 //if (!found)
420 {
421 boost::filesystem::path fontPath;
422 //check if file with font flags exist
423 //if (index != 0)
424 {
425 std::string path = fontPathBase.parent_path().generic_string();
426 std::string fname = fontPathBase.stem().generic_string();
427 std::string ext = fontPathBase.extension().generic_string();
428
429#if defined(ANDROID)
430 FILE* fcheck = 0;
431 if ((scol_font_flags & BT_FONT_BOLD) && (scol_font_flags & BT_FONT_ITALIC))
432 if ((fcheck = SCfopen((path + "/" + fname + "bi" + ext).c_str(), "rb")) != 0)
433 {
434 fclose(fcheck);
435 fontPath = boost::filesystem::path(path + "/" + fname + "bi" + ext);
436 }
437 if (fontPath.empty() && (scol_font_flags & BT_FONT_BOLD))
438 if ((fcheck = SCfopen((path + "/" + fname + "b" + ext).c_str(), "rb")) != 0)
439 {
440 fclose(fcheck);
441 fontPath = boost::filesystem::path(path + "/" + fname + "b" + ext);
442 }
443
444 if (fontPath.empty() && scol_font_flags & BT_FONT_ITALIC)
445 if ((fcheck = SCfopen((path + "/" + fname + "i" + ext).c_str(), "rb")) != 0)
446 {
447 fclose(fcheck);
448 fontPath = boost::filesystem::path(path + "/" + fname + "i" + ext);
449 }
450#else
451 if ((scol_font_flags & BT_FONT_BOLD) && (scol_font_flags & BT_FONT_ITALIC))
452 if (boost::filesystem::exists(path + "/" + fname + "bi" + ext))
453 fontPath = boost::filesystem::path(path + "/" + fname + "bi" + ext);
454
455 if (fontPath.empty() && (scol_font_flags & BT_FONT_BOLD))
456 if (boost::filesystem::exists(path + "/" + fname + "b" + ext))
457 fontPath = boost::filesystem::path(path + "/" + fname + "b" + ext);
458
459 if (fontPath.empty() && scol_font_flags & BT_FONT_ITALIC)
460 if (boost::filesystem::exists(path + "/" + fname + "i" + ext))
461 fontPath = boost::filesystem::path(path + "/" + fname + "i" + ext);
462
463#endif
464 }
465
466 if (fontPath.empty())
467 fontPath = fontPathBase;
468
469 if (!font->ft2->loadFontData(fontPath.generic_string(), 0))
470 {
471 MMechostr(MSKDEBUG, "Warning on _CRBTfontFromFile : %s, not found", fontPath.generic_string().c_str());
472 SAFE_DELETE(font);
473 MMset(m, 0, NIL);
474 return 0;
475 }
476 }
477
478 // Other parameters
479 // ------------
480 if (scol_font_flags & BT_FONT_ITALIC)
481 font->face |= cv::FONT_ITALIC;
482
483 if (scol_font_flags & BT_FONT_ANTIALIAS)
484 font->linetype = cv::LINE_AA;
485 else
486 font->linetype = 8;
487
488 font->thickness = -1;
489
490 // Font scale
491 // ------------
492 cv::Size cv_font_size = font->ft2->getTextSize(BT_CHARSETREF, 16, 1, NULL);
493 font->scale = (float)(cv_font_size.height) / 11.0f;
494 font->size = (int)((float)scol_font_size * font->scale);
495
496 if (scol_font_flags & BT_FONT_HOLLOW)
497 font->thickness = 1 + (int)((font->scale * 1.55f) - 1.0f);
498
499 font->xoffset = 2;
500 font->baseSize = font->ft2->getTextSize(BT_CHARSETREF, font->size, font->thickness, NULL);
501
502 // Store to tuple
503 // ----------------
504 if ((MMpushPointer(m, font) != 0))
505 {
506 if (font)
507 SAFE_DELETE(font);
508 MMset(m, 0, NIL);
509 return MERRMEM;
510 }
511
512 return OBJcreate(m, SObjBTFont, SCOL_PTR font, NIL, 0);
513#endif
514}
515
523int _DSBTfont(mmachine m)
524{
525 int obj = MMget(m, 0);
526 if (obj == NIL)
527 {
528 MMset(m, 0, NIL);
529 return 0;
530 }
531
532 OBJdelTM(m, SObjBTFont, obj);
533
534 MMset(m, 0, ITOM(0));
535 return 0;
536}
537
552// TO TEST WITH ObjBTFont
553int _BTDRAWtextBitmap(mmachine m)
554{
555#ifdef SCOL_DEBUG
556 MMechostr(MSKDEBUG, "_BTDRAWtextBitmap");
557#endif
558
559 // Stack parameters
560 int itext = MMpull(m);
561 int icolor = MMpull(m);
562 int ialignmentFlags = MMpull(m);
563 int icoordinates = MMpull(m);
564 int ifont = MMpull(m);
565 int ibitmap = MMget(m, 0);
566 if (ibitmap == NIL || itext == NIL || icoordinates == NIL || ifont == NIL)
567 {
568 MMechostr(MSKDEBUG, "input bitmap, text or coordinates are NIL");
569 MMset(m, 0, NIL);
570 return 0;
571 }
572
573 // Mandatory parameters
574 // --------------------
575 // bitmap
576 PtrObjVoid ptr_bitmap = (PtrObjVoid)MMstart(m, MTOP(ibitmap));
577 PtrObjBitmap obj_bitmap = (PtrObjBitmap)MMstart(m, MTOP(ptr_bitmap->Buffer));
578
579 cv::Mat bitmap = ConversionTools::ScolBitmapToMat(obj_bitmap);
580 if (bitmap.empty())
581 {
582 MMechostr(MSKDEBUG, "input bitmap, is empty");
583 MMset(m, 0, NIL);
584 return 0;
585 }
586
587 // coordinates
588 int iposx = MMfetch(m, MTOP(icoordinates), 0);
589 int iposy = MMfetch(m, MTOP(icoordinates), 1);
590 if (iposx == NIL || iposy == NIL)
591 {
592 MMechostr(MSKDEBUG, "coordinates x or y are NIL");
593 MMset(m, 0, NIL);
594 return 0;
595 }
596 int posx = MTOI(iposx);
597 int posy = MTOI(iposy);
598
599 cv::Scalar color(0);
600 if (icolor != NIL)
601 {
602 int c = MTOI(icolor) & 0xffffff;
603 color = cv::Scalar((c >> 16) & 255, (c >> 8) & 255, c & 255);
604 }
605
606 // text
607 std::string text = MMstartstr(m, MTOP(itext));
608
609 if (text.empty())
610 {
611 return 0;
612 }
613
614 text = ReplaceAll(text, "\r\n", " ");
615 text = ReplaceAll(text, "\r", " ");
616 text = ReplaceAll(text, "\n", " ");
617
618 PtrObjBTFont obj_font = MMgetPointer<PtrObjBTFont>(m, MTOP(ifont));
619 if (!obj_font)
620 {
621 MMset(m, 0, NIL);
622 return 0;
623 }
624
625 int alignment = BT_TEXT_HORIZ_LEFT | BT_TEXT_VERT_TOP;
626 if (ialignmentFlags != NIL)
627 alignment = MTOI(ialignmentFlags);
628
629 // Alignment to coords
630 // --------------------
631 cv::Point cv_position;
632 cv::Size line_size;
633
634#ifdef BT_USE_FREETYPE
635 if (obj_font->mode)
636 line_size = obj_font->ft2->getTextSize(text, obj_font->size, obj_font->thickness, NULL);
637 else
638#endif
639 line_size = cv::getTextSize(text, obj_font->face, obj_font->scale, obj_font->thickness, NULL);
640
641 // Horizontal alignment
642 switch (alignment & BT_TEXT_HORIZ_MASK)
643 {
645 cv_position.x = posx;
646 break;
648 cv_position.x = posx - line_size.width;
649 break;
651 cv_position.x = posx - line_size.width / 2;
652 break;
654 cv_position.x = posx - line_size.width / 2;
655 break;
656 default:
657 cv_position.x = posx;
658 break;
659 }
660
661 // Vertical alignment
662 switch (alignment & BT_TEXT_VERT_MASK)
663 {
664 case BT_TEXT_VERT_TOP:
665 cv_position.y = posy + line_size.height;
666 break;
668 cv_position.y = posy + line_size.height / 2;
669 break;
671 cv_position.y = posy;
672 break;
673 default:
674 cv_position.y = posy + line_size.height;
675 break;
676 }
677
678 // Draw to cv::Mat
679 try
680 {
681#ifdef BT_USE_FREETYPE
682 if (obj_font->mode)
683 obj_font->ft2->putText(bitmap, text, cv_position, obj_font->size, color, obj_font->thickness, obj_font->linetype, true);
684 else
685#endif
686 cv::putText(bitmap, text, cv_position, obj_font->face, obj_font->scale, color, obj_font->thickness, obj_font->linetype);
687 }
688 catch (cv::Exception e)
689 {
690 MMechostr(MSKDEBUG, "error on cv::putText : %s in %s:%s:%d", e.msg.c_str(), e.file.c_str(), e.func.c_str(), e.line);
691 }
692
693#ifdef SCOL_DEBUG
694 cv::line(bitmap, cv::Point(cv_position.x - 4, cv_position.y), cv::Point(cv_position.x, cv_position.y), cv::Scalar(0, 125, 255));
695 cv::line(bitmap, cv::Point(cv_position.x, cv_position.y), cv::Point(cv_position.x, cv_position.y + 4), cv::Scalar(0, 125, 255));
696 cv::line(bitmap, cv::Point(posx - 4, posy), cv::Point(posx + 4, posy), cv::Scalar(0, 255, 125));
697 cv::line(bitmap, cv::Point(posx, posy - 4), cv::Point(posx, posy + 4), cv::Scalar(0, 255, 125));
698#endif
699
700#ifdef SCOL_DEBUG
701 MMechostr(MSKDEBUG, "end _BTDRAWtextBitmap");
702#endif
703 return 0;
704}
705
722// FIX THE COPY PASTA
724{
725#ifdef SCOL_DEBUG
726 MMechostr(MSKDEBUG, "_BTDRAWtextAreaBitmap");
727#endif
728
729 // Stack parameters
730 int itext = MMpull(m);
731 int icolor = MMpull(m);
732 int ialignmentFlags = MMpull(m);
733 int ioffset = MMpull(m);
734 int icoordinates = MMpull(m);
735 int ifont = MMpull(m);
736 int ibitmap = MMget(m, 0);
737 if (ibitmap == NIL || itext == NIL || icoordinates == NIL || ifont == NIL)
738 {
739 MMechostr(MSKDEBUG, "input bitmap, text or coordinates are NIL");
740 MMset(m, 0, NIL);
741 return 0;
742 }
743
744 cv::Scalar color(0);
745 if (icolor != NIL)
746 {
747 int c = MTOI(icolor) & 0xffffff;
748 color = cv::Scalar((c >> 16) & 255, (c >> 8) & 255, c & 255);
749 }
750
751 // Mandatory parameters
752 // --------------------
753 // bitmap
754 PtrObjVoid ptr_bitmap = (PtrObjVoid)MMstart(m, MTOP(ibitmap));
755 PtrObjBitmap obj_bitmap = (PtrObjBitmap)MMstart(m, MTOP(ptr_bitmap->Buffer));
756
757 cv::Mat bitmap = ConversionTools::ScolBitmapToMat(obj_bitmap);
758 if (bitmap.empty())
759 {
760 MMechostr(MSKDEBUG, "input bitmap, is empty");
761 MMset(m, 0, NIL);
762 return 0;
763 }
764
765 //offset
766 cv::Point offset(0, 0);
767 if (ioffset != NIL)
768 {
769 int ioffx = MMfetch(m, MTOP(ioffset), 0);
770 int ioffy = MMfetch(m, MTOP(ioffset), 1);
771
772 if (ioffx != NIL)
773 offset.x = MTOI(ioffx);
774
775 if (ioffy != NIL)
776 offset.y = MTOI(ioffy);
777 }
778
779 // coordinates
780 int iposx = MMfetch(m, MTOP(icoordinates), 0);
781 int iposy = MMfetch(m, MTOP(icoordinates), 1);
782 int iwidth = MMfetch(m, MTOP(icoordinates), 2);
783 int iheight = MMfetch(m, MTOP(icoordinates), 3);
784 if (iposx == NIL || iposy == NIL || iwidth == NIL || iheight == NIL)
785 {
786 MMechostr(MSKDEBUG, "coordinates x, y, or size width, height are NIL");
787 MMset(m, 0, NIL);
788 return 0;
789 }
790 int rect_posx = MTOI(iposx);
791 int rect_posy = MTOI(iposy);
792 int rect_width = MTOI(iwidth);
793 int rect_height = MTOI(iheight);
794
795 // check bounds
796 if (rect_posx >= obj_bitmap->TailleW || rect_posy >= obj_bitmap->TailleH)
797 {
798 MMechostr(MSKRUNTIME, "_BTDRAWtextAreaAlphaBitmap : error, tried to write text outside the bitmap");
799 MMset(m, 0, NIL);
800 return 0;
801 }
802
803 if (rect_width <= 0 || rect_height <= 0)
804 {
805 MMechostr(MSKRUNTIME, "_BTDRAWtextAreaAlphaBitmap : error, negative rect bounds");
806 MMset(m, 0, NIL);
807 return 0;
808 }
809
810 if (rect_posx < 0)
811 rect_posx = 0;
812
813 if (rect_posy < 0)
814 rect_posy = 0;
815
816 if ((rect_posx + rect_width) > obj_bitmap->TailleW)
817 rect_width = obj_bitmap->TailleW - rect_posx;
818
819 if ((rect_posy + rect_height) > obj_bitmap->TailleH)
820 rect_height = obj_bitmap->TailleH - rect_posy;
821
822 // Rect to draw to
823 cv::Rect brect(rect_posx, rect_posy, rect_width, rect_height);
824
825 cv::Mat subBitmap = bitmap(brect);
826
827 // text
828 std::string text = MMstartstr(m, MTOP(itext));
829
830 if (text.empty())
831 {
832 return 0;
833 }
834
835 // font
836 PtrObjBTFont obj_font = MMgetPointer<PtrObjBTFont>(m, MTOP(ifont));
837 if (!obj_font)
838 {
839 MMset(m, 0, NIL);
840 return 0;
841 }
842
843 int alignment = BT_TEXT_HORIZ_LEFT | BT_TEXT_VERT_TOP;
844 if (ialignmentFlags != NIL)
845 alignment = MTOI(ialignmentFlags);
846
847 // Alignment to coords
848 // --------------------
849 cv::Point cv_position;
850 cv::Size line_size;
851 int line_shiftSize;
852 cv::Size base_size = obj_font->baseSize;
853
854 line_shiftSize = (int)((float)base_size.height * obj_font->lineOffset) + abs(obj_font->thickness);
855 std::vector<std::string> lines = word_wrap(text, obj_font, rect_width - (2 * obj_font->xoffset), (alignment & BT_TEXT_WORD_WRAP));
856
857 switch (alignment & BT_TEXT_VERT_MASK)
858 {
859 case BT_TEXT_VERT_TOP:
860 cv_position.y = line_shiftSize - (line_shiftSize - base_size.height) + obj_font->xoffset;
861 break;
863 {
864 if (line_shiftSize * (int)lines.size() < rect_height)
865 {
866 cv_position.y = (rect_height / 2) - (((line_shiftSize * lines.size()) / 2) - base_size.height);
867 }
868 else
869 cv_position.y = line_shiftSize;
870 }
871 break;
873 {
874 if (line_shiftSize * (int)lines.size() < rect_height)
875 {
876 cv_position.y = rect_height - (line_shiftSize * lines.size()) + base_size.height - obj_font->xoffset;
877 }
878 else
879 cv_position.y = line_shiftSize;
880 }
881 break;
882 default:
883 cv_position.y = 0;
884 break;
885 }
886 cv_position.y += offset.y;
887
888 for (unsigned i = 0; i < lines.size(); i++)
889 {
890 if (!lines[i].empty())
891 {
892#ifdef BT_USE_FREETYPE
893 if (obj_font->mode)
894 line_size = obj_font->ft2->getTextSize(lines[i], obj_font->size, obj_font->thickness, NULL);
895 else
896#endif
897 line_size = cv::getTextSize(lines[i], obj_font->face, obj_font->scale, obj_font->thickness, NULL);
898 }
899
900 line_size.height = line_shiftSize;
901
902 switch (alignment & BT_TEXT_HORIZ_MASK)
903 {
905 cv_position.x = obj_font->xoffset;
906 break;
908 cv_position.x = rect_width - line_size.width - obj_font->xoffset;
909 break;
911 cv_position.x = (rect_width / 2) - (line_size.width / 2);
912 break;
914 cv_position.x = obj_font->xoffset;
915 break;
916 default:
917 cv_position.x = obj_font->xoffset;
918 break;
919 }
920 cv_position.x += offset.x;
921
922 // nothing different yet
923 if (!lines[i].empty() && (cv_position.y < rect_height))
924 {
925#ifdef SCOL_DEBUG
926 cv::line(subBitmap, cv::Point(cv_position.x - 4, cv_position.y), cv::Point(cv_position.x, cv_position.y), cv::Scalar(0, 125, 255));
927 cv::line(subBitmap, cv::Point(cv_position.x, cv_position.y), cv::Point(cv_position.x, cv_position.y + 4), cv::Scalar(0, 125, 255));
928#endif
929
930 try
931 {
932#ifdef BT_USE_FREETYPE
933 if (obj_font->mode)
934 obj_font->ft2->putText(bitmap, lines[i], cv_position, obj_font->size, color, obj_font->thickness, obj_font->linetype, true);
935 else
936#endif
937 cv::putText(subBitmap, lines[i], cv_position, obj_font->face, obj_font->scale, color, obj_font->thickness, obj_font->linetype);
938 }
939 catch (cv::Exception e)
940 {
941 MMechostr(MSKDEBUG, "error on cv::putText : %s in %s:%s:%d", e.msg.c_str(), e.file.c_str(), e.func.c_str(), e.line);
942 break;
943 }
944 }
945 cv_position.y += line_shiftSize;
946
947 // no word wrap, draw only first line
948 if ((alignment& BT_TEXT_WORD_WRAP) == 0)
949 break;
950 }
951
952#ifdef SCOL_DEBUG
953 cv::rectangle(subBitmap, cv::Rect(0, 0, rect_width, rect_height), cv::Scalar(255, 0, 0));
954#endif
955
956#ifdef SCOL_DEBUG
957 MMechostr(MSKDEBUG, "end _BTDRAWtextAreaBitmap");
958#endif
959 return 0;
960}
961
978{
979#ifdef SCOL_DEBUG
980 MMechostr(MSKDEBUG, "_BTDRAWtextAlphaBitmap");
981#endif
982
983 // Stack parameters
984 int itext = MMpull(m);
985 int iopacity = MMpull(m);
986 int icolor = MMpull(m);
987 int ialignmentFlags = MMpull(m);
988 int icoordinates = MMpull(m);
989 int ifont = MMpull(m);
990 int ibitmap = MMget(m, 0);
991 if (ibitmap == NIL || itext == NIL || icoordinates == NIL || ifont == NIL)
992 {
993 MMechostr(MSKDEBUG, "input bitmap, text or coordinates are NIL");
994 MMset(m, 0, NIL);
995 return 0;
996 }
997
998 cv::Scalar color(0);
999 if (icolor != NIL)
1000 {
1001 int c = MTOI(icolor) & 0xffffff;
1002 color = cv::Scalar((c >> 16) & 255, (c >> 8) & 255, c & 255);
1003 }
1004
1005 int opacity = 255;
1006 if (iopacity != NIL)
1007 opacity = MTOI(iopacity) & 0xff;
1008
1009 cv::Scalar alpha = cv::Scalar(opacity);
1010
1011 // Mandatory parameters
1012 // --------------------
1013 // bitmap
1014 int bmp24 = MMfetch(m, MTOP(ibitmap), 0);
1015 int bmp8 = MMfetch(m, MTOP(ibitmap), 1);
1016
1017 // Get scol bitmaps
1018 PtrObjVoid ptr_bitmap = (PtrObjVoid)MMstart(m, MTOP(bmp24));
1019 PtrObjBitmap obj_bitmap = (PtrObjBitmap)MMstart(m, MTOP(ptr_bitmap->Buffer));
1020
1021 PtrObjVoid ptr_bitmap8 = (PtrObjVoid)MMstart(m, MTOP(bmp8));
1022 PtrObjBitmap obj_bitmap8 = (PtrObjBitmap)MMstart(m, MTOP(ptr_bitmap8->Buffer));
1023
1024 cv::Mat bitmap = ConversionTools::ScolBitmapToMat(obj_bitmap);
1025 if (bitmap.empty())
1026 {
1027 MMechostr(MSKDEBUG, "input bitmap, is empty");
1028 MMset(m, 0, NIL);
1029 return 0;
1030 }
1031
1032 cv::Mat bitmap8 = ConversionTools::ScolBitmapToMat(obj_bitmap8);
1033 if (bitmap8.empty())
1034 {
1035 MMechostr(MSKDEBUG, "input bitmap8, is empty");
1036 MMset(m, 0, NIL);
1037 return 0;
1038 }
1039
1040 // coordinates
1041 int iposx = MMfetch(m, MTOP(icoordinates), 0);
1042 int iposy = MMfetch(m, MTOP(icoordinates), 1);
1043 if (iposx == NIL || iposy == NIL)
1044 {
1045 MMechostr(MSKDEBUG, "coordinates x or y are NIL");
1046 MMset(m, 0, NIL);
1047 return 0;
1048 }
1049 int posx = MTOI(iposx);
1050 int posy = MTOI(iposy);
1051
1052 // text
1053 std::string text = MMstartstr(m, MTOP(itext));
1054
1055 if (text.empty())
1056 {
1057 return 0;
1058 }
1059
1060 text = ReplaceAll(text, "\r\n", " ");
1061 text = ReplaceAll(text, "\r", " ");
1062 text = ReplaceAll(text, "\n", " ");
1063
1064 // font
1065 PtrObjBTFont obj_font = MMgetPointer<PtrObjBTFont>(m, MTOP(ifont));
1066 if (!obj_font)
1067 {
1068 MMset(m, 0, NIL);
1069 return 0;
1070 }
1071
1072 int alignment = BT_TEXT_HORIZ_LEFT | BT_TEXT_VERT_TOP;
1073 if (ialignmentFlags != NIL)
1074 alignment = MTOI(ialignmentFlags);
1075
1076 // Alignment to coords
1077 // --------------------
1078 cv::Point cv_position;
1079 cv::Size line_size;
1080#ifdef BT_USE_FREETYPE
1081 if (obj_font->mode)
1082 line_size = obj_font->ft2->getTextSize(text, obj_font->size, obj_font->thickness, NULL);
1083 else
1084#endif
1085 line_size = cv::getTextSize(text, obj_font->face, obj_font->scale, obj_font->thickness, NULL);
1086
1087 // Horizontal alignment
1088 switch (alignment & BT_TEXT_HORIZ_MASK)
1089 {
1090 case BT_TEXT_HORIZ_LEFT:
1091 cv_position.x = posx;
1092 break;
1094 cv_position.x = posx - line_size.width;
1095 break;
1097 cv_position.x = posx - line_size.width / 2;
1098 break;
1100 cv_position.x = posx - line_size.width / 2;
1101 break;
1102 default:
1103 cv_position.x = posx;
1104 break;
1105 }
1106
1107 // Vertical alignment
1108 switch (alignment & BT_TEXT_VERT_MASK)
1109 {
1110 case BT_TEXT_VERT_TOP:
1111 cv_position.y = posy + line_size.height;
1112 break;
1114 cv_position.y = posy + line_size.height / 2;
1115 break;
1117 cv_position.y = posy;
1118 break;
1119 default:
1120 cv_position.y = posy + line_size.height;
1121 break;
1122 }
1123
1124 // Draw to cv::Mat
1125 try
1126 {
1127#ifdef BT_USE_FREETYPE
1128 if (obj_font->mode)
1129 {
1130 obj_font->ft2->putText(bitmap, text, cv_position, obj_font->size, color, obj_font->thickness, obj_font->linetype, true);
1131 obj_font->ft2->putText(bitmap8, text, cv_position, obj_font->size, alpha, obj_font->thickness, obj_font->linetype, true);
1132 }
1133 else
1134#endif
1135 {
1136 cv::putText(bitmap, text, cv_position, obj_font->face, obj_font->scale, color, obj_font->thickness, obj_font->linetype);
1137 cv::putText(bitmap8, text, cv_position, obj_font->face, obj_font->scale, alpha, obj_font->thickness, obj_font->linetype);
1138 }
1139 }
1140 catch (cv::Exception e)
1141 {
1142 MMechostr(MSKDEBUG, "error on cv::putText : %s in %s:%s:%d", e.msg.c_str(), e.file.c_str(), e.func.c_str(), e.line);
1143 }
1144
1145#ifdef SCOL_DEBUG
1146 cv::line(bitmap, cv::Point(cv_position.x - 4, cv_position.y), cv::Point(cv_position.x, cv_position.y), cv::Scalar(0, 125, 255));
1147 cv::line(bitmap, cv::Point(cv_position.x, cv_position.y), cv::Point(cv_position.x, cv_position.y + 4), cv::Scalar(0, 125, 255));
1148 cv::line(bitmap, cv::Point(posx - 4, posy), cv::Point(posx + 4, posy), cv::Scalar(0, 255, 125));
1149 cv::line(bitmap, cv::Point(posx, posy - 4), cv::Point(posx, posy + 4), cv::Scalar(0, 255, 125));
1150#endif
1151
1152#ifdef SCOL_DEBUG
1153 MMechostr(MSKDEBUG, "end _BTDRAWtextAlphaBitmap");
1154#endif
1155 return 0;
1156}
1157
1176{
1177#ifdef SCOL_DEBUG
1178 MMechostr(MSKDEBUG, "_BTDRAWtextAreaAlphaBitmap\n");
1179#endif
1180
1181 // Stack parameters
1182 int itext = MMpull(m);
1183 int iopacity = MMpull(m);
1184 int icolor = MMpull(m);
1185 int ialignmentFlags = MMpull(m);
1186 int ioffset = MMpull(m);
1187 int icoordinates = MMpull(m);
1188 int ifont = MMpull(m);
1189 int ibitmap = MMget(m, 0);
1190 if (ibitmap == NIL || itext == NIL || icoordinates == NIL || ifont == NIL)
1191 {
1192 MMechostr(MSKDEBUG, "input bitmap, text or coordinates are NIL\n");
1193 MMset(m, 0, NIL);
1194 return 0;
1195 }
1196
1197 // text
1198 std::string text = MMstartstr(m, MTOP(itext));
1199 if (text.empty())
1200 {
1201 MMechostr(MSKRUNTIME, "_BTDRAWtextAreaAlphaBitmap : text is nil\n");
1202 MMset(m, 0, NIL);
1203 return 0;
1204 }
1205
1206 cv::Scalar color(0);
1207 if (icolor != NIL)
1208 {
1209 int c = MTOI(icolor) & 0xffffff;
1210 color = cv::Scalar((c >> 16) & 255, (c >> 8) & 255, c & 255);
1211 }
1212
1213 int opacity = 255;
1214 if (iopacity != NIL)
1215 opacity = MTOI(iopacity) & 0xff;
1216
1217 cv::Scalar alpha = cv::Scalar(opacity);
1218
1219 // Mandatory parameters
1220 // --------------------
1221 // bitmap
1222 int bmp24 = MMfetch(m, MTOP(ibitmap), 0);
1223 int bmp8 = MMfetch(m, MTOP(ibitmap), 1);
1224
1225 // Get scol bitmaps
1226 PtrObjVoid ptr_bitmap = (PtrObjVoid)MMstart(m, MTOP(bmp24));
1227 PtrObjBitmap obj_bitmap = (PtrObjBitmap)MMstart(m, MTOP(ptr_bitmap->Buffer));
1228
1229 PtrObjVoid ptr_bitmap8 = (PtrObjVoid)MMstart(m, MTOP(bmp8));
1230 PtrObjBitmap obj_bitmap8 = (PtrObjBitmap)MMstart(m, MTOP(ptr_bitmap8->Buffer));
1231
1232 cv::Mat bitmap = ConversionTools::ScolBitmapToMat(obj_bitmap);
1233 if (bitmap.empty())
1234 {
1235 MMechostr(MSKDEBUG, "input bitmap, is empty");
1236 MMset(m, 0, NIL);
1237 return 0;
1238 }
1239
1240 cv::Mat bitmap8 = ConversionTools::ScolBitmapToMat(obj_bitmap8);
1241 if (bitmap8.empty())
1242 {
1243 MMechostr(MSKDEBUG, "input bitmap8, is empty");
1244 MMset(m, 0, NIL);
1245 return 0;
1246 }
1247
1248 //offset
1249 cv::Point offset(0, 0);
1250 if (ioffset != NIL)
1251 {
1252 int ioffx = MMfetch(m, MTOP(ioffset), 0);
1253 int ioffy = MMfetch(m, MTOP(ioffset), 1);
1254
1255 if (ioffx != NIL)
1256 offset.x = MTOI(ioffx);
1257
1258 if (ioffy != NIL)
1259 offset.y = MTOI(ioffy);
1260 }
1261
1262 // coordinates
1263 int iposx = MMfetch(m, MTOP(icoordinates), 0);
1264 int iposy = MMfetch(m, MTOP(icoordinates), 1);
1265 int iwidth = MMfetch(m, MTOP(icoordinates), 2);
1266 int iheight = MMfetch(m, MTOP(icoordinates), 3);
1267 if (iposx == NIL || iposy == NIL || iwidth == NIL || iheight == NIL)
1268 {
1269 MMechostr(MSKDEBUG, "coordinates x, y, or size width, height are NIL\n");
1270 MMset(m, 0, NIL);
1271 return 0;
1272 }
1273
1274 int rect_posx = MTOI(iposx);
1275 int rect_posy = MTOI(iposy);
1276 int rect_width = MTOI(iwidth);
1277 int rect_height = MTOI(iheight);
1278
1279 // check bounds
1280 if (rect_posx >= obj_bitmap->TailleW || rect_posy >= obj_bitmap->TailleH)
1281 {
1282 MMechostr(MSKRUNTIME, "_BTDRAWtextAreaAlphaBitmap : error, tried to write text outside the bitmap\n");
1283 MMset(m, 0, NIL);
1284 return 0;
1285 }
1286
1287 if (rect_width <= 0 || rect_height <= 0)
1288 {
1289 MMechostr(MSKRUNTIME, "_BTDRAWtextAreaAlphaBitmap : error, negative rect bounds\n");
1290 MMset(m, 0, NIL);
1291 return 0;
1292 }
1293
1294 if (rect_posx < 0)
1295 rect_posx = 0;
1296
1297 if (rect_posy < 0)
1298 rect_posy = 0;
1299
1300 if ((rect_posx + rect_width) > obj_bitmap->TailleW)
1301 rect_width = obj_bitmap->TailleW - rect_posx;
1302
1303 if ((rect_posy + rect_height) > obj_bitmap->TailleH)
1304 rect_height = obj_bitmap->TailleH - rect_posy;
1305
1306 // Rect to draw to
1307 cv::Rect brect(rect_posx, rect_posy, rect_width, rect_height);
1308
1309 cv::Mat subBitmap = bitmap(brect);
1310 cv::Mat subBitmap8 = bitmap8(brect);
1311
1312 // font
1313 PtrObjBTFont obj_font = MMgetPointer<PtrObjBTFont>(m, MTOP(ifont));
1314 if (!obj_font)
1315 {
1316 MMset(m, 0, NIL);
1317 return 0;
1318 }
1319
1320 int alignment = BT_TEXT_HORIZ_LEFT | BT_TEXT_VERT_TOP;
1321 if (ialignmentFlags != NIL)
1322 alignment = MTOI(ialignmentFlags);
1323
1324 // Alignment to coords
1325 // --------------------
1326 cv::Point cv_position;
1327 cv::Size line_size;
1328 cv::Size base_size = obj_font->baseSize;
1329
1330 int line_shiftSize = (int)((float)base_size.height * obj_font->lineOffset) + abs(obj_font->thickness);
1331 std::vector<std::string> lines = word_wrap(text, obj_font, rect_width - (2 * obj_font->xoffset), (alignment & BT_TEXT_WORD_WRAP));
1332
1333 switch (alignment & BT_TEXT_VERT_MASK)
1334 {
1335 case BT_TEXT_VERT_TOP:
1336 cv_position.y = line_shiftSize - (line_shiftSize - base_size.height) + obj_font->xoffset;
1337 break;
1339 {
1340 if (line_shiftSize * (int)lines.size() < rect_height)
1341 cv_position.y = (rect_height / 2) - (((line_shiftSize * lines.size()) / 2) - base_size.height);
1342 else
1343 cv_position.y = line_shiftSize;
1344 }
1345 break;
1347 {
1348 if (line_shiftSize * (int)lines.size() < rect_height)
1349 cv_position.y = rect_height - (line_shiftSize * lines.size()) + base_size.height - obj_font->xoffset;
1350 else
1351 cv_position.y = line_shiftSize;
1352 }
1353 break;
1354 default:
1355 cv_position.y = 0;
1356 break;
1357 }
1358 cv_position.y += offset.y;
1359
1360 for (unsigned i = 0; i < lines.size(); i++)
1361 {
1362 if (!lines[i].empty())
1363 {
1364#ifdef BT_USE_FREETYPE
1365 if (obj_font->mode)
1366 line_size = obj_font->ft2->getTextSize(lines[i], obj_font->size, obj_font->thickness, NULL);
1367 else
1368#endif
1369 line_size = cv::getTextSize(lines[i], obj_font->face, obj_font->scale, obj_font->thickness, NULL);
1370 }
1371
1372 line_size.height = line_shiftSize;
1373
1374 switch (alignment & BT_TEXT_HORIZ_MASK)
1375 {
1376 case BT_TEXT_HORIZ_LEFT:
1377 cv_position.x = obj_font->xoffset;
1378 break;
1380 cv_position.x = rect_width - line_size.width - obj_font->xoffset;
1381 break;
1383 cv_position.x = (rect_width / 2) - (line_size.width / 2);
1384 break;
1386 cv_position.x = obj_font->xoffset;
1387 break;
1388 default:
1389 cv_position.x = obj_font->xoffset;
1390 break;
1391 }
1392 cv_position.x += offset.x;
1393
1394 if (!lines[i].empty() && (cv_position.y < rect_height))
1395 {
1396#ifdef SCOL_DEBUG
1397 cv::line(subBitmap, cv::Point(cv_position.x - 4, cv_position.y), cv::Point(cv_position.x, cv_position.y), cv::Scalar(0, 125, 255));
1398 cv::line(subBitmap, cv::Point(cv_position.x, cv_position.y), cv::Point(cv_position.x, cv_position.y + 4), cv::Scalar(0, 125, 255));
1399 cv::rectangle(subBitmap, cv::Rect(cv_position.x, cv_position.y - base_size.height, line_size.width, line_shiftSize), cv::Scalar(0, 125, 255));
1400#endif
1401
1402 if (!lines[i].empty())
1403 {
1404 try
1405 {
1406#ifdef BT_USE_FREETYPE
1407 if (obj_font->mode)
1408 {
1409 obj_font->ft2->putText(subBitmap, lines[i], cv_position, obj_font->size, color, obj_font->thickness, obj_font->linetype, true);
1410 obj_font->ft2->putText(subBitmap8, lines[i], cv_position, obj_font->size, alpha, obj_font->thickness, obj_font->linetype, true);
1411 }
1412 else
1413#endif
1414 {
1415 cv::putText(subBitmap, lines[i], cv_position, obj_font->face, obj_font->scale, color, obj_font->thickness, obj_font->linetype);
1416 cv::putText(subBitmap8, lines[i], cv_position, obj_font->face, obj_font->scale, alpha, obj_font->thickness, obj_font->linetype);
1417 }
1418 }
1419 catch (cv::Exception e)
1420 {
1421 MMechostr(MSKDEBUG, "error on cv::putText : %s in %s:%s:%d", e.msg.c_str(), e.file.c_str(), e.func.c_str(), e.line);
1422 break;
1423 }
1424 }
1425 }
1426 cv_position.y += line_shiftSize;
1427
1428 // no word wrap, draw only first line
1429 if ((alignment & BT_TEXT_WORD_WRAP) == 0)
1430 break;
1431 }
1432
1433#ifdef SCOL_DEBUG
1434 cv::rectangle(subBitmap, cv::Rect(0, 0, rect_width, rect_height), cv::Scalar(255, 0, 0));
1435#endif
1436
1437#ifdef SCOL_DEBUG
1438 MMechostr(MSKDEBUG, "end _BTDRAWtextAreaAlphaBitmap\n");
1439#endif
1440 return 0;
1441}
1442
1451int _BTGETtextSize(mmachine m)
1452{
1453#ifdef SCOL_DEBUG
1454 MMechostr(MSKDEBUG, "_BTGETtextSize\n");
1455#endif
1456
1457 int itext = MMpull(m);
1458 int ifont = MMget(m, 0);
1459
1460 if (ifont == NIL)
1461 {
1462 MMset(m, 0, NIL);
1463 return 0;
1464 }
1465
1466 std::string text = (itext == NIL) ? "" : MMstartstr(m, MTOP(itext));
1467
1468 std::vector<std::string> lines;
1469
1470 text = ReplaceAll(text, "\r\n", "\n");
1471 text = ReplaceAll(text, "\r", "\n");
1472 std::istringstream is_line(text);
1473 std::string line;
1474
1475 while (getline(is_line, line, '\n'))
1476 {
1477 lines.push_back(line);
1478 }
1479
1480 // font
1481 PtrObjBTFont obj_font = MMgetPointer<PtrObjBTFont>(m, MTOP(ifont));
1482 if (!obj_font)
1483 {
1484 MMset(m, 0, NIL);
1485 return 0;
1486 }
1487
1488 int line_shiftSize = (int)((float)obj_font->baseSize.height * obj_font->lineOffset) + abs(obj_font->thickness);
1489 cv::Size linesize;
1490 cv::Size textsize(0, 0);
1491
1492 for (unsigned i = 0; i < lines.size(); i++)
1493 {
1494 if (!lines[i].empty())
1495 {
1496#ifdef BT_USE_FREETYPE
1497 if (obj_font->mode)
1498 linesize = obj_font->ft2->getTextSize(lines[i], obj_font->size, obj_font->thickness, NULL);
1499 else
1500#endif
1501 linesize = cv::getTextSize(lines[i], obj_font->face, obj_font->scale, obj_font->thickness, NULL);
1502 }
1503 else
1504 linesize.width = 0;
1505 linesize.height = line_shiftSize;
1506
1507 if (textsize.width < linesize.width)
1508 textsize.width = linesize.width;
1509 textsize.height += linesize.height;
1510 }
1511
1512 textsize.width += obj_font->xoffset * 2;
1513 textsize.height += obj_font->xoffset * 2;
1514
1515 int itextsize = MMmalloc(m, 2, TYPETAB);
1516 if (itextsize == NIL)
1517 {
1518 MMset(m, 0, NIL);
1519 return 0;
1520 }
1521
1522 MMstore(m, itextsize, 0, ITOM(textsize.width));
1523 MMstore(m, itextsize, 1, ITOM(textsize.height));
1524 MMset(m, 0, PTOM(itextsize));
1525
1526#ifdef SCOL_DEBUG
1527 MMechostr(MSKDEBUG, "end _BTGETtextSize\n");
1528#endif
1529 return 0;
1530}
1531
1543{
1544#ifdef SCOL_DEBUG
1545 MMechostr(MSKDEBUG, "_BTGETtextAreaHeight\n");
1546#endif
1547
1548 int iwidth = MMpull(m);
1549 int ialignmentFlags = MMpull(m);
1550 int itext = MMpull(m);
1551 int ifont = MMget(m, 0);
1552
1553 if (ifont == NIL || iwidth == NIL)
1554 {
1555 MMset(m, 0, NIL);
1556 return 0;
1557 }
1558
1559 std::string text = (itext == NIL) ? "" : MMstartstr(m, MTOP(itext));
1560
1561 // font
1562 PtrObjBTFont obj_font = MMgetPointer<PtrObjBTFont>(m, MTOP(ifont));
1563 if (!obj_font)
1564 {
1565 MMset(m, 0, NIL);
1566 return 0;
1567 }
1568
1569 int width = MTOI(iwidth);
1570
1571 cv::Size linesize;
1572 linesize.height = (int)((float)obj_font->baseSize.height * obj_font->lineOffset) + abs(obj_font->thickness);
1573
1574 //should calc the size with the formated text ? (\r\n ...)
1575 if (!text.empty())
1576 {
1577 int alignment = BT_TEXT_HORIZ_LEFT | BT_TEXT_VERT_TOP;
1578 if (ialignmentFlags != NIL)
1579 alignment = MTOI(ialignmentFlags);
1580
1581 // Alignment to coords
1582 // --------------------
1583 cv::Point cv_position;
1584 int line_shiftSize = (int)((float)obj_font->baseSize.height * obj_font->lineOffset) + abs(obj_font->thickness);
1585 std::vector<std::string> lines = word_wrap(text, obj_font, width - (2 * obj_font->xoffset), (alignment &BT_TEXT_WORD_WRAP));
1586
1587 cv_position.y = obj_font->xoffset;
1588 for (unsigned i = 0; i < lines.size(); i++)
1589 {
1590 if (!lines[i].empty())
1591 {
1592#ifdef BT_USE_FREETYPE
1593 if (obj_font->mode)
1594 linesize = obj_font->ft2->getTextSize(lines[i], obj_font->size, obj_font->thickness, NULL);
1595 else
1596#endif
1597 linesize = cv::getTextSize(lines[i], obj_font->face, obj_font->scale, obj_font->thickness, NULL);
1598 }
1599
1600 linesize.height = line_shiftSize;
1601
1602 switch (alignment & BT_TEXT_HORIZ_MASK)
1603 {
1604 case BT_TEXT_HORIZ_LEFT:
1605 cv_position.x = obj_font->xoffset;
1606 break;
1608 cv_position.x = width - linesize.width - obj_font->xoffset;;
1609 break;
1611 cv_position.x = (width / 2) - (linesize.width / 2);
1612 break;
1614 cv_position.x = obj_font->xoffset;
1615 break;
1616 default:
1617 cv_position.x = obj_font->xoffset;
1618 break;
1619 }
1620
1621 cv_position.y += line_shiftSize;
1622
1623 // no word wrap, draw only first line
1624 if ((alignment & BT_TEXT_WORD_WRAP) == 0)
1625 break;
1626 }
1627 linesize.height = cv_position.y + obj_font->xoffset;
1628 }
1629
1630 MMset(m, 0, ITOM(linesize.height));
1631
1632#ifdef SCOL_DEBUG
1633 MMechostr(MSKDEBUG, "end _BTGETtextAreaHeight\n");
1634#endif
1635 return 0;
1636}
std::vector< std::string > word_wrap(std::string input, PtrObjBTFont obj_font, int max_width, int splitlines)
std::string ReplaceAll(std::string str, const std::string &from, const std::string &to)
int destroyCVFont(mmachine m, SCOL_PTR_TYPE handsys, int obj)
#define BT_TEXT_HORIZ_LEFT
#define BT_FONT_ITALIC
#define BT_TEXT_HORIZ_RIGHT
#define BT_TEXT_VERT_MASK
#define BT_TEXT_VERT_CENTER
#define BT_TEXT_VERT_TOP
#define BT_TEXT_HORIZ_JUSTIFIED
#define BT_FONT_BOLD
#define BT_FONT_FILLED
#define BT_CHARSET
#define BT_FONT_ANTIALIAS
#define BT_TEXT_HORIZ_CENTERED
#define BT_FONT_SCRIPT
#define BT_TEXT_VERT_BOTTOM
#define BT_CHARSETREF
#define BT_TEXT_HORIZ_MASK
#define BT_FONT_SANS
#define BT_TEXT_WORD_WRAP
#define BT_FONT_SERIF
int SObjBTFont
#define BT_FONT_HOLLOW
static cv::Mat ScolBitmapToMat(PtrObjBitmap scolBitmap)
cv::Size baseSize
int _CRBTfont(mmachine m)
_CRBTfont : Creates a ObjBTFont object Prototype: fun [Chn S I I F] ObjBTFont
int _CRBTfontFromFile(mmachine m)
_CRBTfontFromFile : Creates a ObjBTFont object Prototype: fun [Chn P I I F] ObjBTFont
int _BTDRAWtextAlphaBitmap(mmachine m)
_BTDRAWtextAlphaBitmap : Draws a text to a bitmap Prototype: fun [AlphaBitmap ObjBTFont [I I] I I I S...
int _BTDRAWtextAreaAlphaBitmap(mmachine m)
_BTDRAWtextAreaAlphaBitmap : Draws a text to an alpha bitmap, within a defined area Prototype: fun [A...
int _BTDRAWtextBitmap(mmachine m)
_BTDRAWtextBitmap : Draws a text to a bitmap Prototype: fun [ObjBitmap S ObjBTFont [I I] I I] ObjBitm...
int _BTGETtextSize(mmachine m)
_BTGETtextSize : Gets the length of a text line Prototype: fun [ObjBTFont S] [I I]
int _BTGETtextAreaHeight(mmachine m)
_BTGETtextAreaHeight : Gets the height of a formated text area Prototype: fun [ObjBTFont S I I] I
int _DSBTfont(mmachine m)
_DSBTfont : Deletes a cv font object Prototype: fun [ObjBTFont] I
int _BTDRAWtextAreaBitmap(mmachine m)
_BTDRAWtextAreaBitmap : Draws a text to a bitmap, within a defined area Prototype: fun [ObjBitmap Obj...
static type & get(std::string name)
static bool has(std::string name)
static bool initialized
static std::map< std::string, type > font_to_cv
static void initialize()