[Perl]Font::Freetype实例 - 字符轮廓填充

头像
523066680
Administrator
Administrator
帖子: 357
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 32 times
Been thanked: 32 times
联系:

[Perl]Font::Freetype实例 - 字符轮廓填充

帖子 #1 523066680 » 2017年10月21日 18:04

Code: [全选] [展开/收缩] [Download] (Untitled.pl)
  1. =info
  2.     Font::Freetype + OpenGL 字符轮廓填充
  3.     523066680
  4.     2017-10
  5. =cut
  6.  
  7. use autodie;
  8. use utf8;
  9. use Encode;
  10. use Font::FreeType;
  11. use feature 'state';
  12. use OpenGL qw/ :all /;
  13. use OpenGL::Config;
  14.  
  15. BEGIN
  16. {    
  17.     use IO::Handle;
  18.     STDOUT->autoflush(1);
  19.  
  20.     our $WinID;
  21.     our $HEIGHT = 500;
  22.     our $WIDTH  = 500;
  23.  
  24.     our ($font, $size) = ("C:/windows/fonts/msyh.ttf", 32);
  25.     our $dpi = 100;
  26.  
  27.     our $face = Font::FreeType->new->face($font);
  28.     $face->set_char_size($size, $size, $dpi, $dpi);
  29.  
  30.     our $tobj;
  31.     our ($rx, $ry, $rz) = (0.0, 0.0, 0.0);
  32. }
  33.  
  34. INIT
  35. {
  36.     our %TEXT;
  37.     print "Loading contours ... ";
  38.     my $code;
  39.     my $char;
  40.     foreach $code (0x00..0x7F)
  41.     {
  42.         $char = chr( $code );
  43.         $TEXT{ $char } = get_contour( $char );
  44.     }
  45.  
  46.     foreach $char (split //, "年月日期数据")
  47.     {
  48.         $TEXT{ $char } = get_contour( $char );
  49.     }
  50.     print "Done\n";
  51. }
  52.  
  53. &main();
  54.  
  55. sub draw_box_lines
  56. {
  57.     glBegin(GL_LINES);
  58.     glColor3f(1.0, 0.0, 0.0);
  59.     glVertex3f(-200.0, 0.0, 0.0);
  60.     glVertex3f(200.0, 0.0, 0.0);
  61.     glVertex3f(0.0, -200.0, 0.0);
  62.     glVertex3f(0.0, 200.0, 0.0);
  63.     glEnd();
  64. }
  65.  
  66. sub draw_character
  67. {
  68.     our @TEXT;
  69.     my $char = shift;
  70.     my $cts;
  71.     gluTessBeginPolygon($tobj);
  72.     for $cts ( @{$TEXT{$char}->{outline}} )
  73.     {
  74.         gluTessBeginContour($tobj);
  75.         grep { gluTessVertex_p($tobj, @$_, 0.0 ) } @$cts;
  76.         gluTessEndContour($tobj);
  77.     }
  78.     gluTessEndPolygon($tobj);
  79. }
  80.  
  81. sub draw_string
  82. {
  83.     my $s = shift;
  84.     for my $c ( split //, $s )
  85.     {
  86.         draw_character($c);
  87.         glTranslatef($TEXT{$c}->{right}, 0.0, 0.0);
  88.     }
  89. }
  90.  
  91. sub display
  92. {
  93.     state $iter = 0;
  94.     state $ti = 0;
  95.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  96.  
  97.     glPushMatrix();
  98.     glRotatef($rx, 1.0, 0.0, 0.0);
  99.     glRotatef($ry, 0.0, 1.0, 0.0);
  100.     glRotatef($rz, 0.0, 0.0, 1.0);
  101.  
  102.     draw_box_lines();
  103.  
  104.     glColor3f(1.0, 1.0, 1.0);
  105.     draw_string("ab:?ge数据QT");
  106.  
  107.     glPopMatrix();
  108.     $iter++;
  109.     glutSwapBuffers();
  110. }
  111.  
  112. sub idle
  113. {
  114.     sleep 0.02;
  115.     glutPostRedisplay();
  116. }
  117.  
  118. sub init
  119. {
  120.     glClearColor(0.0, 0.0, 0.0, 0.5);
  121.     glPointSize(4.0);
  122.     glLineWidth(1.0);
  123.     glEnable(GL_BLEND);
  124.     glEnable(GL_DEPTH_TEST);
  125.     # glEnable(GL_POINT_SMOOTH);
  126.     glEnable(GL_LINE_SMOOTH);
  127.     glShadeModel(GL_FLAT);
  128.  
  129.     $tobj = gluNewTess();
  130.  
  131.     # gluTessCallback($tobj, GLU_TESS_VERTEX, \&glVertex3f );
  132.     # #gluTessCallback($tobj, GLU_TESS_VERTEX, \&vertexCallback);
  133.     # gluTessCallback($tobj, GLU_TESS_BEGIN,  \&beginCallback);
  134.     # gluTessCallback($tobj, GLU_TESS_END,    \&endCallback);
  135.     # gluTessCallback($tobj, GLU_TESS_ERROR,  \&errorCallback);
  136.  
  137.     gluTessCallback($tobj, GLU_TESS_BEGIN,     'DEFAULT');
  138.     gluTessCallback($tobj, GLU_TESS_END,       'DEFAULT');
  139.     gluTessCallback($tobj, GLU_TESS_VERTEX,    'DEFAULT');
  140.     gluTessCallback($tobj, GLU_TESS_COMBINE,   'DEFAULT');
  141.     gluTessCallback($tobj, GLU_TESS_ERROR,     'DEFAULT');
  142.     gluTessCallback($tobj, GLU_TESS_EDGE_FLAG, 'DEFAULT');
  143. }
  144.  
  145. sub reshape
  146. {
  147.     my ($w, $h) = (shift, shift);
  148.     #Same with screen size
  149.     state $hz_half = $WIDTH/2.0;
  150.     state $vt_half = $HEIGHT/2.0;
  151.     state $fa = 250.0;
  152.  
  153.     glViewport(0, 0, $w, $h);
  154.     glMatrixMode(GL_PROJECTION);
  155.     glLoadIdentity();
  156.     glOrtho(-$hz_half, $hz_half, -$vt_half, $vt_half, 0.0, $fa*2.0);
  157.     #gluPerspective( 90.0, 1.0, 1.0, $fa*2.0 );
  158.     glMatrixMode(GL_MODELVIEW);
  159.     glLoadIdentity();
  160.     gluLookAt(0.0,0.0,$fa, 0.0,0.0,0.0, 0.0,1.0, $fa);
  161. }
  162.  
  163. sub hitkey
  164. {
  165.     our $WinID;
  166.     my $k = lc(chr(shift));
  167.  
  168.     if ( $k eq 'q') { quit() }
  169.     if ( $k eq 'w') { $rx+=10.0 }
  170.     if ( $k eq 's') { $rx-=10.0 }
  171.     if ( $k eq 'a') { $ry-=10.0 }
  172.     if ( $k eq 'd') { $ry+=10.0 }
  173.     if ( $k eq 'j') { $rz+=10.0 }
  174.     if ( $k eq 'k') { $rz-=10.0 }
  175. }
  176.  
  177. sub quit
  178. {
  179.     glutDestroyWindow( $WinID );
  180.     exit;
  181. }
  182.  
  183. sub main
  184. {
  185.     glutInit();
  186.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE |GLUT_DEPTH | GLUT_MULTISAMPLE  );
  187.     glutInitWindowSize($WIDTH, $HEIGHT);
  188.     glutInitWindowPosition(100, 100);
  189.     our $WinID = glutCreateWindow("Display");
  190.     &init();
  191.     glutDisplayFunc(\&display);
  192.     glutReshapeFunc(\&reshape);
  193.     glutKeyboardFunc(\&hitkey);
  194.     glutIdleFunc(\&idle);
  195.     glutMainLoop();
  196. }
  197.  
  198. BEZIER_FUNCTION:
  199. {
  200.     sub pointOnLine
  201.     {
  202.         my ($x1, $y1, $x2, $y2, $t) = @_;
  203.         return (
  204.             ($x2-$x1)*$t + $x1,
  205.             ($y2-$y1)*$t + $y1
  206.         );
  207.     }
  208.  
  209.     sub pointOnQuadBezier
  210.     {
  211.         my ($x1, $y1, $x2, $y2, $x3, $y3, $t) = @_;
  212.         return
  213.             pointOnLine(
  214.                    pointOnLine( $x1, $y1, $x2, $y2, $t ),
  215.                    pointOnLine( $x2, $y2, $x3, $y3, $t ),
  216.                    $t
  217.             );
  218.     }
  219. }
  220.  
  221. TESS_CALLBACK_FUNCTION:
  222. {
  223.     sub beginCallback  { glBegin( $_[0] ); print( $_[0] ," ") }
  224.     sub endCallback    { glEnd(); }
  225.     sub errorCallback  { print gluErrorString($_[0]),"\n"; quit(); }
  226.     sub vertexCallback { glVertex3f( @_ ); }
  227. }
  228.  
  229. sub get_contour
  230. {
  231.     our $glyph;
  232.     my $char = shift;
  233.     #previous x, y
  234.     my $px, $py, $parts, $step;
  235.     my @contour = ();
  236.     my $ncts    = -1;
  237.    
  238.     $parts = 5;
  239.     $glyph = $face->glyph_from_char($char) || return undef;
  240.  
  241.     $glyph->outline_decompose(
  242.         move_to  =>
  243.             sub
  244.             {
  245.                 ($px, $py) = @_;
  246.                 $ncts++;
  247.                 push @{$contour[$ncts]}, [$px, $py];
  248.             },
  249.         line_to  =>
  250.             sub
  251.             {
  252.                 ($px, $py) = @_;
  253.                 push @{$contour[$ncts]}, [$px, $py];
  254.             },
  255.         conic_to =>
  256.             sub
  257.             {
  258.                 for ($step = 0.0; $step <= $parts; $step+=1.0)
  259.                 {
  260.                     push @{$contour[$ncts]},
  261.                         [ pointOnQuadBezier( $px, $py, @_[2,3,0,1], $step/$parts ) ];
  262.                 }
  263.                 ($px, $py) = @_;
  264.             },
  265.         cubic_to => sub { warn "cubic\n"; }
  266.     );
  267.  
  268.     return {
  269.         outline => [@contour],
  270.         right   => $glyph->horizontal_advance(),
  271.     };
  272. }

回到 “模块”

在线用户

用户浏览此论坛: 没有注册用户 和 1 访客