- メインページ
- モジュール
- ネームスペース
- データ構造
- ファイル

- ファイル一覧
- グローバル

drawing.h
説明を見る。
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28
33 #ifndef __INCLUDE_MIST_DRAWING__
34 #define __INCLUDE_MIST_DRAWING__
35
36
37 #ifndef __INCLUDE_MIST_H__
38 #include "mist.h"
39 #endif
40
41 #ifndef __INCLUDE_BITMAP_H__
42 #include "bitmap.h"
43 #endif
44
45 #include <cmath>
46
47 #ifdef MIST_USE_DRAW_TEXT
48 #include <ft2build.h>
49 #include FT_FREETYPE_H
50 #endif
51
52
53 // mist名前空間の始まり
54 _MIST_BEGIN
55
56
57
58
66
67
68
80 template < class T, class Allocator >
81 void draw_line( array2< T, Allocator > &image,
82 typename array2< T, Allocator >::difference_type x1,
83 typename array2< T, Allocator >::difference_type y1,
84 typename array2< T, Allocator >::difference_type x2,
85 typename array2< T, Allocator >::difference_type y2,
86 typename array2< T, Allocator >::value_type color = typename array2< T, Allocator >::value_type( ) )
87 {
88 typedef typename array2< T, Allocator >::difference_type difference_type;
89 difference_type dx, dy;
90 difference_type sx, sy;
91 difference_type x, y, e, i;
92 difference_type w = static_cast< difference_type >( image.width( ) );
93 difference_type h = static_cast< difference_type >( image.height( ) );
94
95 dx = std::abs( static_cast< int >( x2 - x1 ) );
96 dy = std::abs( static_cast< int >( y2 - y1 ) );
97 sx = ( x2 - x1 >= 0 ) ? 1 : -1;
98 sy = ( y2 - y1 >= 0 ) ? 1 : -1;
99 x = x1;
100 y = y1;
101 if( dx >= dy )
102 {
103 e = -dx;
104 for( i = 0 ; i <= dx ; i++ )
105 {
106 if( x >= 0 && x < w && y >= 0 && y < h )
107 {
108 image( x, y ) = color;
109 }
110 x += sx;
111 e += 2 * dy;
112
113 if( e >= 0 )
114 {
115 y += sy;
116 e -= 2 * dx;
117 }
118 }
119 }
120 else
121 {
122 e = -dy;
123 for( i = 0 ; i <= dy ; i++ )
124 {
125 if( x >= 0 && x < w && y >= 0 && y < h )
126 {
127 image( x, y ) = color;
128 }
129 y += sy;
130 e += 2 * dx;
131 if( e >= 0 )
132 {
133 x += sx;
134 e -= 2 * dy;
135 }
136 }
137 }
138 }
139
140
141
153 template < size_t BITS >
154 void draw_line( bitmap< BITS > &image,
155 typename bitmap< BITS >::difference_type x1,
156 typename bitmap< BITS >::difference_type y1,
157 typename bitmap< BITS >::difference_type x2,
158 typename bitmap< BITS >::difference_type y2,
159 typename bitmap< BITS >::value_type color = typename bitmap< BITS >::value_type( ) )
160 {
161 typedef typename bitmap< BITS >::difference_type difference_type;
162 difference_type dx, dy;
163 difference_type sx, sy;
164 difference_type x, y, e, i;
165 difference_type w = static_cast< difference_type >( image.width( ) );
166 difference_type h = static_cast< difference_type >( image.height( ) );
167
168 dx = std::abs( static_cast< int >( x2 - x1 ) );
169 dy = std::abs( static_cast< int >( y2 - y1 ) );
170 sx = ( x2 - x1 >= 0 ) ? 1 : -1;
171 sy = ( y2 - y1 >= 0 ) ? 1 : -1;
172 x = x1;
173 y = y1;
174 if( dx >= dy )
175 {
176 e = -dx;
177 for( i = 0 ; i <= dx ; i++ )
178 {
179 if( x >= 0 && x < w && y >= 0 && y < h )
180 {
181 image( x, y ) = color;
182 }
183 x += sx;
184 e += 2 * dy;
185
186 if( e >= 0 )
187 {
188 y += sy;
189 e -= 2 * dx;
190 }
191 }
192 }
193 else
194 {
195 e = -dy;
196 for( i = 0 ; i <= dy ; i++ )
197 {
198 if( x >= 0 && x < w && y >= 0 && y < h )
199 {
200 image( x, y ) = color;
201 }
202 y += sy;
203 e += 2 * dx;
204 if( e >= 0 )
205 {
206 x += sx;
207 e -= 2 * dy;
208 }
209 }
210 }
211 }
212
213
214
228 template < class T, class Allocator >
229 void draw_line( array3< T, Allocator > &image,
230 typename array3< T, Allocator >::difference_type x1,
231 typename array3< T, Allocator >::difference_type y1,
232 typename array3< T, Allocator >::difference_type z1,
233 typename array3< T, Allocator >::difference_type x2,
234 typename array3< T, Allocator >::difference_type y2,
235 typename array3< T, Allocator >::difference_type z2,
236 typename array3< T, Allocator >::value_type color = typename array3< T, Allocator >::value_type( ) )
237 {
238 typedef typename array3< T, Allocator >::difference_type difference_type;
239 difference_type dx, dy, dz;
240 difference_type sx, sy, sz;
241 difference_type x, y, z, e1, e2, i;
242 difference_type w = static_cast< difference_type >( image.width( ) );
243 difference_type h = static_cast< difference_type >( image.height( ) );
244 difference_type d = static_cast< difference_type >( image.depth( ) );
245
246 dx = std::abs( static_cast< int >( x2 - x1 ) );
247 dy = std::abs( static_cast< int >( y2 - y1 ) );
248 dz = std::abs( static_cast< int >( z2 - z1 ) );
249 sx = ( x2 - x1 >= 0 ) ? 1 : -1;
250 sy = ( y2 - y1 >= 0 ) ? 1 : -1;
251 sz = ( z2 - z1 >= 0 ) ? 1 : -1;
252 x = x1;
253 y = y1;
254 z = z1;
255 if( dx >= dy && dx >= dz )
256 {
257 e1 = e2 = -dx;
258 for( i = 0 ; i <= dx ; i++ )
259 {
260 if( x >= 0 && x < w && y >= 0 && y < h && z >= 0 && z < d )
261 {
262 image( x, y, z ) = color;
263 }
264 x += sx;
265 e1 += 2 * dy;
266 e2 += 2 * dz;
267
268 if( e1 >= 0 )
269 {
270 y += sy;
271 e1 -= 2 * dx;
272 }
273
274 if( e2 >= 0 )
275 {
276 z += sz;
277 e2 -= 2 * dx;
278 }
279 }
280 }
281 else if( dy >= dx && dy >= dz )
282 {
283 e1 = e2 = -dy;
284 for( i = 0 ; i <= dy ; i++ )
285 {
286 if( x >= 0 && x < w && y >= 0 && y < h && z >= 0 && z < d )
287 {
288 image( x, y, z ) = color;
289 }
290 y += sy;
291 e1 += 2 * dx;
292 e2 += 2 * dz;
293
294 if( e1 >= 0 )
295 {
296 x += sx;
297 e1 -= 2 * dy;
298 }
299
300 if( e2 >= 0 )
301 {
302 z += sz;
303 e2 -= 2 * dy;
304 }
305 }
306 }
307 else
308 {
309 e1 = e2 = -dz;
310 for( i = 0 ; i <= dz ; i++ )
311 {
312 if( x >= 0 && x < w && y >= 0 && y < h && z >= 0 && z < d )
313 {
314 image( x, y, z ) = color;
315 }
316 z += sz;
317 e1 += 2 * dx;
318 e2 += 2 * dy;
319
320 if( e1 >= 0 )
321 {
322 x += sx;
323 e1 -= 2 * dz;
324 }
325
326 if( e2 >= 0 )
327 {
328 y += sy;
329 e2 -= 2 * dz;
330 }
331 }
332 }
333 }
334
335
336
347 template < class T, class Allocator >
348 void draw_point( array2< T, Allocator > &image,
349 typename array2< T, Allocator >::difference_type x,
350 typename array2< T, Allocator >::difference_type y,
351 typename array2< T, Allocator >::difference_type radius,
352 typename array2< T, Allocator >::value_type value = typename array3< T, Allocator >::value_type( ) )
353 {
354 typedef typename array2< T, Allocator >::difference_type difference_type;
355
356 difference_type is = x - radius;
357 difference_type ie = x + radius;
358 difference_type js = y - radius;
359 difference_type je = y + radius;
360
361 difference_type w = static_cast< difference_type >( image.width( ) );
362 difference_type h = static_cast< difference_type >( image.height( ) );
363
364 if( is < 0 )
365 {
366 is = 0;
367 }
368 if( is >= w )
369 {
370 is = w;
371 ie = w - 1;
372 }
373 if( ie < 0 )
374 {
375 is = 0;
376 ie = -1;
377 }
378 if( ie >= w )
379 {
380 ie = w - 1;
381 }
382
383 if( js < 0 )
384 {
385 js = 0;
386 }
387 if( js >= h )
388 {
389 js = h;
390 je = h - 1;
391 }
392 if( je < 0 )
393 {
394 js = 0;
395 je = -1;
396 }
397 if( je >= h )
398 {
399 je = h - 1;
400 }
401
402 for( difference_type j = js ; j <= je ; j++ )
403 {
404 for( difference_type i = is ; i <= ie ; i++ )
405 {
406 image( i, j ) = value;
407 }
408 }
409 }
410
411
423 template < class T, class Allocator >
424 void draw_point( array3< T, Allocator > &image,
425 typename array3< T, Allocator >::difference_type x,
426 typename array3< T, Allocator >::difference_type y,
427 typename array3< T, Allocator >::difference_type z,
428 typename array3< T, Allocator >::difference_type radius,
429 typename array3< T, Allocator >::value_type value = typename array3< T, Allocator >::value_type( ) )
430 {
431 typedef typename array3< T, Allocator >::difference_type difference_type;
432
433 difference_type is = x - radius;
434 difference_type ie = x + radius;
435 difference_type js = y - radius;
436 difference_type je = y + radius;
437 difference_type ks = z - radius;
438 difference_type ke = z + radius;
439
440 difference_type w = static_cast< difference_type >( image.width( ) );
441 difference_type h = static_cast< difference_type >( image.height( ) );
442 difference_type d = static_cast< difference_type >( image.depth( ) );
443
444 if( is < 0 )
445 {
446 is = 0;
447 }
448 if( is >= w )
449 {
450 is = w;
451 ie = w - 1;
452 }
453 if( ie < 0 )
454 {
455 is = 0;
456 ie = -1;
457 }
458 if( ie >= w )
459 {
460 ie = w - 1;
461 }
462
463 if( js < 0 )
464 {
465 js = 0;
466 }
467 if( js >= h )
468 {
469 js = h;
470 je = h - 1;
471 }
472 if( je < 0 )
473 {
474 js = 0;
475 je = -1;
476 }
477 if( je >= h )
478 {
479 je = h - 1;
480 }
481
482 if( ks < 0 )
483 {
484 ks = 0;
485 }
486 if( ks >= d )
487 {
488 ks = d;
489 ke = d - 1;
490 }
491 if( ke < 0 )
492 {
493 ks = 0;
494 ke = -1;
495 }
496 if( ke >= d )
497 {
498 ke = d - 1;
499 }
500
501 for( difference_type k = ks ; k <= ke ; k++ )
502 {
503 for( difference_type j = js ; j <= je ; j++ )
504 {
505 for( difference_type i = is ; i <= ie ; i++ )
506 {
507 image( i, j, k ) = value;
508 }
509 }
510 }
511 }
512
518 template< typename T, typename Allocator >
519 void set_pixel( array2< T, Allocator > &image,
520 typename array2< T, Allocator >::difference_type x,
521 typename array2< T, Allocator >::difference_type y,
522 const typename array2< T, Allocator >::value_type &value )
523 {
524 typedef typename array2< T, Allocator >::difference_type difference_type;
525
526 // 範囲チェック
527 if( x < 0 || y < 0 || x >= static_cast< difference_type >( image.width( ) ) || y >= static_cast< difference_type >( image.height( ) ) )
528 {
529 return;
530 }
531
532 image( x, y ) = value;
533 }
534
541 template< typename T, typename Allocator >
542 void draw_circle( array2< T, Allocator > &image,
543 typename array2< T, Allocator >::difference_type cx,
544 typename array2< T, Allocator >::difference_type cy,
545 typename array2< T, Allocator >::difference_type r,
546 const typename array2< T, Allocator >::value_type &value )
547 {
548 typename array2< T, Allocator >::difference_type d = 3 - 2 * r;
549 typename array2< T, Allocator >::difference_type dx;
550 typename array2< T, Allocator >::difference_type dy = r;
551
552 // 開始点
553 set_pixel( image, cx, cy + r, value );
554 set_pixel( image, cx, cy - r, value );
555 set_pixel( image, cx + r, cy, value );
556 set_pixel( image, cx - r, cy, value );
557
558 for( dx = 0 ; dx <= dy ; ++dx )
559 {
560 if( d < 0 )
561 {
562 d += 6 + 4 * dx;
563 }
564 else
565 {
566 d += 10 + 4 * dx - 4 * dy--;
567 }
568
569 set_pixel( image, cx + dy, cy + dx, value );
570 set_pixel( image, cx + dx, cy + dy, value );
571 set_pixel( image, cx - dx, cy + dy, value );
572 set_pixel( image, cx - dy, cy + dx, value );
573 set_pixel( image, cx - dy, cy - dx, value );
574 set_pixel( image, cx - dx, cy - dy, value );
575 set_pixel( image, cx + dx, cy - dy, value );
576 set_pixel( image, cx + dy, cy - dx, value );
577 }
578 }
579
587 template< typename T, typename Allocator >
588 void draw_rect( array2< T, Allocator > &image,
589 typename array2< T, Allocator >::difference_type x0,
590 typename array2< T, Allocator >::difference_type y0,
591 typename array2< T, Allocator >::difference_type x1,
592 typename array2< T, Allocator >::difference_type y1,
593 const typename array2< T, Allocator >::value_type &value )
594 {
595 draw_line( image, x0, y0, x1, y0, value );
596 draw_line( image, x0, y0, x0, y1, value );
597 draw_line( image, x1, y0, x1, y1, value );
598 draw_line( image, x0, y1, x1, y1, value );
599 }
600
608 template< typename T, typename Allocator >
609 void fill_rect( array2< T, Allocator > &image,
610 typename array2< T, Allocator >::difference_type x0,
611 typename array2< T, Allocator >::difference_type y0,
612 typename array2< T, Allocator >::difference_type x1,
613 typename array2< T, Allocator >::difference_type y1,
614 const typename array2< T, Allocator >::value_type &value )
615 {
616 typedef typename array2< T, Allocator >::difference_type difference_type;
617
618 x0 = ( 0 < x0 ) ? x0 : 0;
619 y0 = ( 0 < y0 ) ? y0 : 0;
620 x1 = ( x1 < static_cast< difference_type >( image.width() - 1 ) ) ? x1 : static_cast< difference_type >( image.width() - 1 );
621 y1 = ( y1 < static_cast< difference_type >( image.height() - 1 ) ) ? y1 : static_cast< difference_type >( image.height() - 1 );
622
623 for( difference_type y = y0 ; y <= y1 ; ++y )
624 {
625 for( difference_type x = x0 ; x <= x1 ; ++x )
626 {
627 image( x, y ) = value;
628 }
629 }
630 }
631
638 template< typename T, typename Allocator >
639 void draw_crosspoint( array2< T, Allocator > &image,
640 typename array2< T, Allocator >::difference_type cx,
641 typename array2< T, Allocator >::difference_type cy,
642 typename array2< T, Allocator >::difference_type size,
643 const typename array2< T, Allocator >::value_type &value )
644 {
645 draw_line( image, cx - size / 2, cy, cx + size / 2, cy, value );
646 draw_line( image, cx, cy - size / 2, cx, cy + size / 2, value );
647 }
648
649
650
651 #ifdef MIST_USE_DRAW_TEXT
652
653
671 template < typename T, typename Allocator >
672 inline bool draw_text( array2< T, Allocator > &img,
673 char *filename,
674 int px,
675 int py,
676 int size,
677 typename array2< T, Allocator >::value_type color,
678 unsigned long *str,
679 int len )
680 {
681
682 FT_Library library = NULL;
683 FT_Face face = NULL;
684 FT_Error error;
685
686 try
687 {
688 error = FT_Init_FreeType( &library );
689 if ( error )
690 {
691 library = NULL;
692 throw error;
693 }
694
695 error = FT_New_Face( library, filename, 0, &face );
696 if ( error )
697 {
698 face = NULL;
699 throw error;
700 }
701
702 error = FT_Set_Pixel_Sizes( face, 0, size );
703 if ( error )
704 {
705 throw error;
706 }
707
708 int pen_x = px;
709 int pen_y = py;
710 for ( int i = 0; i < len; i++)
711 {
712 FT_UInt glyph_index = FT_Get_Char_Index( face, (FT_ULong)str[i] );
713
714 error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
715 if ( error )
716 {
717 throw error;
718 }
719
720 error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
721 if ( error )
722 {
723 throw error;
724 }
725
726 for (int x = 0; x < face->glyph->bitmap.width; x++)
727 {
728 for (int y = 0; y < face->glyph->bitmap.rows; y++)
729 {
730 int xx = x + pen_x + face->glyph->bitmap_left;
731 int yy = y + pen_y - face->glyph->bitmap_top;
732 if ( ( 0 <= xx ) && ( xx < (int)img.width() ) && ( 0 <= yy ) && ( yy < (int)img.height() ) )
733 {
734 // alpha blending
735 T img_value = img(xx, yy);
736 double str_value = static_cast< double > ( face->glyph->bitmap.buffer[ x + y * face->glyph->bitmap.width] ) / 255.0;
737 img(xx, yy) = static_cast< typename array2<T>::value_type > ( str_value * color + (1.0 - str_value) * img_value );
738 }
739 }
740 }
741 pen_x += face->glyph->advance.x >> 6;
742
743 }
744
745 FT_Done_Face(face);
746 FT_Done_FreeType(library);
747
748 }
749 catch ( ... )
750 {
751 if (face != NULL)
752 {
753 FT_Done_Face(face);
754 }
755 if (library != NULL)
756 {
757 FT_Done_FreeType(library);
758 }
759 return false;
760 }
761
762 return true;
763
764 }
765
766
767
784 template < typename T, typename Allocator >
785 inline bool draw_text( array2< T, Allocator > &img,
786 char *filename,
787 int px,
788 int py,
789 int size,
790 typename array2< T, Allocator >::value_type color,
791 char *str )
792 {
793 int len = strlen(str);
794
795 unsigned long *str_ulong = new unsigned long[len];
796
797 for (int i = 0; i < len; i++)
798 {
799 str_ulong[i] = (FT_ULong)str[i];
800 }
801
802 bool result = draw_text( img, filename, px, py, size, color, str_ulong, len );
803
804 delete []str_ulong;
805
806 return result;
807
808 }
809
810
811 #endif // MIST_USE_DRAW_TEXT
812
813
815 // 直線や円の描画グループの終わり
816
817
818 // mist名前空間の終わり
819 _MIST_END
820
821
822 #endif // __INCLUDE_MIST_DRAWING__
823