Files
harbour-core/contrib/hbcairo/tests/fancytxt.prg
Przemysław Czerpak 96ca3fe470 2014-01-21 20:41 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* Makefile
  * config/*
  * contrib/*
  * doc/*
  * extras/*
  * include/*
  * lib/*
  * package/*
  * src/*
  * tests/*
  * utils/*
    * removed empty lines left after removed '$' + 'Id' + '$' identifiers
2014-01-21 20:41:05 +01:00

191 lines
6.1 KiB
Plaintext

#require "hbcairo"
PROCEDURE Main()
LOCAL hSurface
hSurface := cairo_pdf_surface_create( "fancytxt.pdf", 566.9, 793.7 ) // 200x280 mm in pt
draw( hSurface )
cairo_surface_destroy( hSurface )
hSurface := cairo_image_surface_create( "fancytxt.pdf", 567, 794 )
draw( hSurface )
cairo_surface_write_to_png( hSurface, "fancytxt.png" )
cairo_surface_destroy( hSurface )
RETURN
PROCEDURE draw( hSurface )
LOCAL hCairo, hPath
hCairo := cairo_create( hSurface )
cairo_set_tolerance( hCairo, 0.01 )
// Draw base line
cairo_move_to( hCairo, 50, 650 )
cairo_rel_line_to( hCairo, 250, 50 )
cairo_rel_curve_to( hCairo, 100, 20, 200, -50, 200, -150 )
cairo_rel_curve_to( hCairo, 0, -400, -300, -100, -400, -300 )
hPath := cairo_copy_path_flat( hCairo )
cairo_set_line_width( hCairo, 1 )
cairo_set_source_rgb( hCairo, 0.6, 0.0, 0.0 )
cairo_stroke( hCairo )
// Draw text
cairo_new_path( hCairo )
cairo_select_font_face( hCairo, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL )
cairo_set_font_size( hCairo, 72 )
cairo_move_to( hCairo, 0, -5 )
cairo_text_path( hCairo, "Welcome to the world of Harbour..." )
// Transform
map_path_onto( hCairo, hPath )
cairo_path_destroy( hPath )
// Paint
cairo_set_line_cap( hCairo, CAIRO_LINE_CAP_ROUND )
cairo_set_source_rgb( hCairo, 0.2, 0.1, 0.8 )
cairo_fill_preserve( hCairo )
cairo_set_line_width( hCairo, 1 )
cairo_set_source_rgb( hCairo, 0.2, 0.2, 0.2 )
cairo_stroke( hCairo )
cairo_show_page( hCairo )
cairo_destroy( hCairo )
RETURN
PROCEDURE map_path_onto( hCairo, hPath )
LOCAL hCurrentPath, aLengths, hIterator, nI, aPoints
hCurrentPath := cairo_copy_path( hCairo )
aLengths := path_lengths( hPath )
hIterator := cairo_path_iterator_create( hCurrentPath )
DO WHILE cairo_path_iterator_next( hIterator ) != NIL
IF Len( aPoints := cairo_path_iterator_get_points( hIterator ) ) > 0
FOR nI := 1 TO Len( aPoints )
transform_point( @aPoints[ nI, 1 ], @aPoints[ nI, 2 ], hPath, aLengths )
NEXT
cairo_path_iterator_set_points( hIterator, aPoints )
ENDIF
ENDDO
cairo_path_iterator_destroy( hIterator )
cairo_append_path( hCairo, hCurrentPath )
RETURN
STATIC PROCEDURE transform_point( nX, nY, hPath, aLengths )
LOCAL hIterator, nI, nNX, nNY, nDX, nDY, nRatio, nType, aLast, aPoints, nK1, nK2
nNX := nX
nNY := nY
hIterator := cairo_path_iterator_create( hPath )
nI := 1
DO WHILE ( nType := cairo_path_iterator_next( hIterator ) ) != NIL
aPoints := cairo_path_iterator_get_points( hIterator )
IF nNX <= aLengths[ nI ] .AND. nType != CAIRO_PATH_MOVE_TO
EXIT
ENDIF
nNX -= aLengths[ nI ]
nI++
IF nType == CAIRO_PATH_MOVE_TO .OR. nType == CAIRO_PATH_LINE_TO
aLast := aPoints[ 1 ]
ELSEIF nType == CAIRO_PATH_CURVE_TO
aLast := aPoints[ 3 ]
ENDIF
ENDDO
IF nType == CAIRO_PATH_MOVE_TO
ELSEIF nType == CAIRO_PATH_LINE_TO
nRatio := nNX / aLengths[ nI ]
nX := aLast[ 1 ] * ( 1 - nRatio ) + aPoints[ 1, 1 ] * nRatio
nY := aLast[ 2 ] * ( 1 - nRatio ) + aPoints[ 1, 2 ] * nRatio
nDX := -( aLast[ 1 ] - aPoints[ 1, 1 ] )
nDY := -( aLast[ 2 ] - aPoints[ 1, 2 ] )
nRatio := nNY / aLengths[ nI ]
nX += -nDY * nRatio
nY += nDX * nRatio
ELSEIF nType == CAIRO_PATH_CURVE_TO
nX := aLast[ 1 ] * ( 1 - nRatio ) ^ 3 + 3 * aPoints[ 1, 1 ] * ( 1 - nRatio ) ^ 2 * nRatio + 3 * aPoints[ 2, 1 ] * ( 1 - nRatio ) * nRatio ^ 2 + aPoints[ 3, 1 ] * nRatio ^ 3
nY := aLast[ 2 ] * ( 1 - nRatio ) ^ 3 + 3 * aPoints[ 1, 2 ] * ( 1 - nRatio ) ^ 2 * nRatio + 3 * aPoints[ 2, 2 ] * ( 1 - nRatio ) * nRatio ^ 2 + aPoints[ 3, 2 ] * nRatio ^ 3
nK1 := 1 - 4 * nRatio + 3 * nRatio ^ 2
nK2 := 2 * nRatio - 3 * nRatio ^ 2
nDX := -3 * aLast[ 1 ] * ( 1 - nRatio ) ^ 2 + 3 * aPoints[ 1, 1 ] * nK1 + 3 * aPoints[ 2, 1 ] * nK2 + 3 * aPoints[ 3, 1 ] * nRatio ^ 2
nDY := -3 * aLast[ 2 ] * ( 1 - nRatio ) ^ 2 + 3 * aPoints[ 1, 2 ] * nK1 + 3 * aPoints[ 2, 2 ] * nK2 + 3 * aPoints[ 3, 2 ] * nRatio ^ 2
nRatio := nNY / Sqrt( nDX * nDX + nDY * nDY )
nX += -nDY * nRatio
nY += nDX * nRatio
ENDIF
cairo_path_iterator_destroy( hIterator )
RETURN
STATIC FUNC path_lengths( hPath )
LOCAL hIterator, nType, aLast, aRet, aPoints, nLen
aRet := {}
hIterator := cairo_path_iterator_create( hPath )
DO WHILE ( nType := cairo_path_iterator_next( hIterator ) ) != NIL
aPoints := cairo_path_iterator_get_points( hIterator )
nLen := 0
IF nType == CAIRO_PATH_MOVE_TO
aLast := aPoints[ 1 ]
ELSEIF nType == CAIRO_PATH_LINE_TO
nLen := distance( aLast[ 1 ], aLast[ 2 ], aPoints[ 1, 1 ], aPoints[ 1, 2 ] )
aLast := aPoints[ 1 ]
ELSEIF nType == CAIRO_PATH_CURVE_TO
nLen := curve_length( aLast[ 1 ], aLast[ 2 ], aPoints[ 1, 1 ], aPoints[ 1, 2 ], ;
aPoints[ 2, 1 ], aPoints[ 2, 2 ], aPoints[ 3, 1 ], aPoints[ 3, 2 ] )
aLast := aPoints[ 3 ]
ENDIF
AAdd( aRet, nLen )
ENDDO
cairo_path_iterator_destroy( hIterator )
RETURN aRet
STATIC FUNC distance( nX1, nY1, nX2, nY2 )
RETURN Sqrt( ( nX1 - nX2 ) ^ 2 + ( nY1 - nY2 ) ^ 2 )
STATIC FUNC curve_length( nX1, nY1, nX2, nY2, nX3, nY3, nX4, nY4 )
LOCAL nLength := 0, hSurface, hCairo, hPath, hIterator, nType, aLast, aPoints
hSurface := cairo_image_surface_create( CAIRO_FORMAT_A8, 0, 0 )
hCairo := cairo_create( hSurface )
cairo_move_to( hCairo, nX1, nY1 )
cairo_curve_to( hCairo, nX2, nY2, nX3, nY3, nX4, nY4 )
hPath := cairo_copy_path_flat( hCairo )
hIterator := cairo_path_iterator_create( hPath )
DO WHILE ( nType := cairo_path_iterator_next( hIterator, @aPoints ) ) != NIL
IF nType == CAIRO_PATH_MOVE_TO
aLast := aPoints
ELSEIF nType == CAIRO_PATH_LINE_TO
nLength += distance( aLast[ 1 ], aLast[ 2 ], aPoints[ 1 ], aPoints[ 2 ] )
aLast := aPoints
ENDIF
ENDDO
cairo_path_iterator_destroy( hIterator )
cairo_path_destroy( hPath )
cairo_destroy( hCairo )
cairo_surface_destroy( hSurface )
RETURN nLength